@dialtribe/react-sdk 0.1.0-alpha.10 → 0.1.0-alpha.12

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.
@@ -2,10 +2,10 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { Component, ReactNode, ErrorInfo } from 'react';
3
3
 
4
4
  /**
5
- * DialTribe SDK Context
5
+ * Dialtribe SDK Context
6
6
  * Manages session token and auto-refresh across all SDK components
7
7
  */
8
- interface DialTribeContextValue {
8
+ interface DialtribeContextValue {
9
9
  /** Current session token */
10
10
  sessionToken: string | null;
11
11
  /** Update the session token (called automatically on refresh) */
@@ -17,7 +17,7 @@ interface DialTribeContextValue {
17
17
  /** Optional API base URL override */
18
18
  apiBaseUrl?: string;
19
19
  }
20
- interface DialTribeProviderProps {
20
+ interface DialtribeProviderProps {
21
21
  /** Session token from your backend (required) */
22
22
  sessionToken: string;
23
23
  /** Called when the API returns a refreshed token via X-Session-Token header */
@@ -34,70 +34,70 @@ interface DialTribeProviderProps {
34
34
  children: React$1.ReactNode;
35
35
  }
36
36
  /**
37
- * DialTribe Provider
37
+ * Dialtribe Provider
38
38
  *
39
39
  * Wraps your app to provide session token authentication to all SDK components.
40
40
  *
41
41
  * @example
42
42
  * ```tsx
43
43
  * // Production (default)
44
- * <DialTribeProvider
44
+ * <DialtribeProvider
45
45
  * sessionToken="sess_xxx..."
46
46
  * onTokenRefresh={(newToken) => setToken(newToken)}
47
47
  * onTokenExpired={() => router.push('/login')}
48
48
  * >
49
49
  * <App />
50
- * </DialTribeProvider>
50
+ * </DialtribeProvider>
51
51
  *
52
52
  * // Local development (explicit)
53
- * <DialTribeProvider
53
+ * <DialtribeProvider
54
54
  * sessionToken="sess_xxx..."
55
55
  * apiBaseUrl="http://localhost:3001/api/public/v1"
56
56
  * onTokenRefresh={(newToken) => setToken(newToken)}
57
57
  * >
58
58
  * <App />
59
- * </DialTribeProvider>
59
+ * </DialtribeProvider>
60
60
  *
61
61
  * // Local development (via env var - recommended)
62
62
  * // Set NEXT_PUBLIC_DIALTRIBE_API_URL=http://localhost:3001/api/public/v1 in .env
63
- * <DialTribeProvider sessionToken="sess_xxx...">
63
+ * <DialtribeProvider sessionToken="sess_xxx...">
64
64
  * <App />
65
- * </DialTribeProvider>
65
+ * </DialtribeProvider>
66
66
  * ```
67
67
  */
68
- declare function DialTribeProvider({ sessionToken: initialToken, onTokenRefresh, onTokenExpired, apiBaseUrl, children, }: DialTribeProviderProps): react_jsx_runtime.JSX.Element;
68
+ declare function DialtribeProvider({ sessionToken: initialToken, onTokenRefresh, onTokenExpired, apiBaseUrl, children, }: DialtribeProviderProps): react_jsx_runtime.JSX.Element;
69
69
  /**
70
- * Hook to access DialTribe context
70
+ * Hook to access Dialtribe context
71
71
  *
72
- * @throws Error if used outside DialTribeProvider
72
+ * @throws Error if used outside DialtribeProvider
73
73
  *
74
74
  * @example
75
75
  * ```tsx
76
- * const { sessionToken, setSessionToken } = useDialTribe();
76
+ * const { sessionToken, setSessionToken } = useDialtribe();
77
77
  * ```
78
78
  */
79
- declare function useDialTribe(): DialTribeContextValue;
79
+ declare function useDialtribe(): DialtribeContextValue;
80
80
  /**
81
- * Hook to optionally access DialTribe context
82
- * Returns null if not within a DialTribeProvider (doesn't throw)
81
+ * Hook to optionally access Dialtribe context
82
+ * Returns null if not within a DialtribeProvider (doesn't throw)
83
83
  *
84
84
  * @example
85
85
  * ```tsx
86
- * const context = useDialTribeOptional();
86
+ * const context = useDialtribeOptional();
87
87
  * const sessionToken = context?.sessionToken ?? propSessionToken;
88
88
  * ```
89
89
  */
90
- declare function useDialTribeOptional(): DialTribeContextValue | null;
90
+ declare function useDialtribeOptional(): DialtribeContextValue | null;
91
91
 
92
92
  /**
93
- * DialTribe API Client
93
+ * Dialtribe API Client
94
94
  *
95
- * Handles all API communication with DialTribe endpoints.
95
+ * Handles all API communication with Dialtribe endpoints.
96
96
  * Automatically manages session token refresh via X-Session-Token headers.
97
97
  *
98
98
  * Supports configurable API base URL for development:
99
99
  * 1. Via environment variable: NEXT_PUBLIC_DIALTRIBE_API_URL
100
- * 2. Via apiBaseUrl prop on DialTribeProvider (takes precedence)
100
+ * 2. Via apiBaseUrl prop on DialtribeProvider (takes precedence)
101
101
  *
102
102
  * Defaults to production URL if neither is specified.
103
103
  */
@@ -109,8 +109,9 @@ declare const ENDPOINTS: {
109
109
  readonly broadcast: (id: number) => string;
110
110
  readonly contentPlay: `${string}/content/play`;
111
111
  readonly presignedUrl: `${string}/media/presigned-url`;
112
- readonly sessionStart: `${string}/session/start`;
113
- readonly sessionPing: `${string}/session/ping`;
112
+ readonly audienceStart: `${string}/audiences/start`;
113
+ readonly audiencePing: `${string}/audiences/ping`;
114
+ readonly sessionPing: `${string}/sessions/ping`;
114
115
  };
115
116
  interface ApiClientConfig {
116
117
  /** Session token for authentication */
@@ -127,17 +128,17 @@ interface ApiClientConfig {
127
128
  apiBaseUrl?: string;
128
129
  }
129
130
  /**
130
- * DialTribe API Client
131
+ * Dialtribe API Client
131
132
  *
132
- * Low-level client for making authenticated requests to DialTribe API.
133
+ * Low-level client for making authenticated requests to Dialtribe API.
133
134
  * Handles session token auto-refresh automatically.
134
135
  */
135
- declare class DialTribeClient {
136
+ declare class DialtribeClient {
136
137
  private config;
137
138
  private endpoints;
138
139
  constructor(config: ApiClientConfig);
139
140
  /**
140
- * Make an authenticated request to DialTribe API
141
+ * Make an authenticated request to Dialtribe API
141
142
  *
142
143
  * Automatically:
143
144
  * - Adds Authorization header with session token
@@ -303,8 +304,8 @@ interface TranscriptData {
303
304
  words?: TranscriptWord[];
304
305
  }
305
306
 
306
- interface BroadcastPlayerProps {
307
- /** Broadcast data from DialTribe API */
307
+ interface DialtribePlayerProps {
308
+ /** Broadcast data from Dialtribe API */
308
309
  broadcast: Broadcast;
309
310
  /** Optional: App ID for tracking */
310
311
  appId?: string;
@@ -334,72 +335,28 @@ interface BroadcastPlayerProps {
334
335
  enableKeyboardShortcuts?: boolean;
335
336
  }
336
337
  /**
337
- * BroadcastPlayer - Core media player component (no modal wrapper)
338
+ * DialtribePlayer - Media player component for Dialtribe broadcasts
338
339
  *
339
340
  * Plays video/audio broadcasts with transcript, waveform visualization, and clip creation.
340
- * Uses DialTribeClient for authenticated API calls.
341
+ * For modal or fullscreen display, wrap with the Overlay component.
341
342
  *
342
343
  * @example
343
344
  * ```tsx
344
- * <BroadcastPlayer
345
- * broadcast={broadcast}
346
- * appId="app_123"
347
- * contentId={456}
348
- * />
349
- * ```
350
- */
351
- declare function BroadcastPlayer({ broadcast, appId, contentId, foreignId, foreignTier, renderClipCreator, onError, className, enableKeyboardShortcuts, }: BroadcastPlayerProps): react_jsx_runtime.JSX.Element;
352
-
353
- interface BroadcastPlayerModalProps {
354
- /** Broadcast data from DialTribe API */
355
- broadcast: Broadcast;
356
- /** Whether modal is open */
357
- isOpen: boolean;
358
- /** Called when modal should close */
359
- onClose: () => void;
360
- /** Optional: App ID for tracking */
361
- appId?: string;
362
- /** Optional: Content ID for tracking */
363
- contentId?: number;
364
- /** Foreign user ID from partner system (any tier) */
365
- foreignId?: string;
366
- /** Tier name from partner system (e.g., 'guest', 'member', 'subscriber_gold') */
367
- foreignTier?: string;
368
- /**
369
- * Optional render prop for clip creator
370
- * If provided, the "Create Clip" button will be shown and this will be called when clicked
371
- */
372
- renderClipCreator?: (props: {
373
- isOpen: boolean;
374
- onClose: () => void;
375
- sourceVideoUrl?: string;
376
- sourceAudioUrl?: string;
377
- sourceDuration: number;
378
- onPauseParent: () => void;
379
- }) => React.ReactNode;
380
- /** Optional: Custom CSS classes for the player */
381
- className?: string;
382
- /** Optional: Enable keyboard shortcuts (Space, arrows, M, F, etc.). Default: false */
383
- enableKeyboardShortcuts?: boolean;
384
- }
385
- /**
386
- * BroadcastPlayerModal - Modal wrapper for BroadcastPlayer
345
+ * // Inline (embedded in page)
346
+ * <DialtribePlayer broadcast={broadcast} />
387
347
  *
388
- * Provides a modal overlay with ESC key handling and backdrop click to close.
389
- * Uses the new BroadcastPlayer component for all player functionality.
348
+ * // Modal (wrap with Overlay)
349
+ * <Overlay mode="modal" isOpen={show} onClose={() => setShow(false)}>
350
+ * <DialtribePlayer broadcast={broadcast} />
351
+ * </Overlay>
390
352
  *
391
- * @example
392
- * ```tsx
393
- * <BroadcastPlayerModal
394
- * broadcast={broadcast}
395
- * isOpen={showModal}
396
- * onClose={() => setShowModal(false)}
397
- * appId="app_123"
398
- * contentId={456}
399
- * />
353
+ * // Fullscreen (wrap with Overlay)
354
+ * <Overlay mode="fullscreen" isOpen={show} onClose={() => setShow(false)}>
355
+ * <DialtribePlayer broadcast={broadcast} />
356
+ * </Overlay>
400
357
  * ```
401
358
  */
402
- declare function BroadcastPlayerModal({ broadcast, isOpen, onClose, appId, contentId, foreignId, foreignTier, renderClipCreator, className, enableKeyboardShortcuts, }: BroadcastPlayerModalProps): react_jsx_runtime.JSX.Element | null;
359
+ declare function DialtribePlayer({ broadcast, appId, contentId, foreignId, foreignTier, renderClipCreator, onError, className, enableKeyboardShortcuts, }: DialtribePlayerProps): react_jsx_runtime.JSX.Element;
403
360
 
404
361
  interface Props {
405
362
  children: ReactNode;
@@ -433,7 +390,7 @@ interface State {
433
390
  * - Logs errors for debugging
434
391
  * - Allows graceful recovery
435
392
  */
436
- declare class BroadcastPlayerErrorBoundary extends Component<Props, State> {
393
+ declare class DialtribePlayerErrorBoundary extends Component<Props, State> {
437
394
  constructor(props: Props);
438
395
  static getDerivedStateFromError(error: Error): Partial<State>;
439
396
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
@@ -487,6 +444,50 @@ interface LoadingSpinnerProps {
487
444
  */
488
445
  declare function LoadingSpinner({ text, size, variant, }: LoadingSpinnerProps): react_jsx_runtime.JSX.Element;
489
446
 
447
+ /** Display mode for the overlay */
448
+ type DialtribeOverlayMode = "modal" | "fullscreen";
449
+ interface DialtribeOverlayProps {
450
+ /** Whether the overlay is open */
451
+ isOpen: boolean;
452
+ /** Called when the overlay should close */
453
+ onClose: () => void;
454
+ /** Display mode: "modal" (centered with backdrop) or "fullscreen" (fills viewport) */
455
+ mode?: DialtribeOverlayMode;
456
+ /** Content to display inside the overlay */
457
+ children: React.ReactNode;
458
+ /** Optional: aria-label for accessibility */
459
+ ariaLabel?: string;
460
+ /** Optional: Show close button. Default: true */
461
+ showCloseButton?: boolean;
462
+ /** Optional: Close on backdrop click. Default: true */
463
+ closeOnBackdropClick?: boolean;
464
+ /** Optional: Close on ESC key. Default: true */
465
+ closeOnEsc?: boolean;
466
+ }
467
+ /**
468
+ * DialtribeOverlay - Reusable modal/fullscreen overlay component
469
+ *
470
+ * Provides a consistent overlay experience with:
471
+ * - Focus management (traps focus, restores on close)
472
+ * - ESC key to close
473
+ * - Backdrop click to close
474
+ * - Accessible with proper ARIA attributes
475
+ *
476
+ * @example
477
+ * ```tsx
478
+ * // Modal mode (centered with backdrop blur)
479
+ * <DialtribeOverlay isOpen={show} onClose={() => setShow(false)} mode="modal">
480
+ * <MyContent />
481
+ * </DialtribeOverlay>
482
+ *
483
+ * // Fullscreen mode (fills entire viewport)
484
+ * <DialtribeOverlay isOpen={show} onClose={() => setShow(false)} mode="fullscreen">
485
+ * <MyContent />
486
+ * </DialtribeOverlay>
487
+ * ```
488
+ */
489
+ declare function DialtribeOverlay({ isOpen, onClose, mode, children, ariaLabel, showCloseButton, closeOnBackdropClick, closeOnEsc, }: DialtribeOverlayProps): react_jsx_runtime.JSX.Element | null;
490
+
490
491
  /**
491
492
  * Format seconds to time string (HH:MM:SS or MM:SS)
492
493
  *
@@ -556,4 +557,4 @@ declare const HTTP_STATUS: {
556
557
  };
557
558
  type HttpStatusCode = typeof HTTP_STATUS[keyof typeof HTTP_STATUS];
558
559
 
559
- export { type ApiClientConfig as A, BroadcastPlayer as B, CDN_DOMAIN as C, DialTribeProvider as D, ENDPOINTS as E, HTTP_STATUS as H, LoadingSpinner as L, type TranscriptWord as T, type DialTribeContextValue as a, type DialTribeProviderProps as b, DialTribeClient as c, DIALTRIBE_API_BASE as d, type BroadcastPlayerProps as e, BroadcastPlayerModal as f, type BroadcastPlayerModalProps as g, BroadcastPlayerErrorBoundary as h, AudioWaveform as i, type Broadcast as j, type TranscriptSegment as k, type TranscriptData as l, formatTime as m, buildBroadcastCdnUrl as n, buildBroadcastS3KeyPrefix as o, type HttpStatusCode as p, useDialTribeOptional as q, useDialTribe as u };
560
+ export { type ApiClientConfig as A, type Broadcast as B, CDN_DOMAIN as C, DialtribeProvider as D, ENDPOINTS as E, HTTP_STATUS as H, LoadingSpinner as L, type TranscriptWord as T, type DialtribeContextValue as a, type DialtribeProviderProps as b, DialtribeClient as c, DIALTRIBE_API_BASE as d, DialtribePlayer as e, type DialtribePlayerProps as f, DialtribePlayerErrorBoundary as g, AudioWaveform as h, DialtribeOverlay as i, type DialtribeOverlayProps as j, type DialtribeOverlayMode as k, type TranscriptSegment as l, type TranscriptData as m, formatTime as n, buildBroadcastCdnUrl as o, buildBroadcastS3KeyPrefix as p, type HttpStatusCode as q, useDialtribeOptional as r, useDialtribe as u };
@@ -0,0 +1,3 @@
1
+ export { A as ApiClientConfig, h as AudioWaveform, B as Broadcast, C as CDN_DOMAIN, d as DIALTRIBE_API_BASE, c as DialtribeClient, a as DialtribeContextValue, i as DialtribeOverlay, k as DialtribeOverlayMode, j as DialtribeOverlayProps, e as DialtribePlayer, g as DialtribePlayerErrorBoundary, f as DialtribePlayerProps, D as DialtribeProvider, b as DialtribeProviderProps, E as ENDPOINTS, H as HTTP_STATUS, q as HttpStatusCode, L as LoadingSpinner, m as TranscriptData, l as TranscriptSegment, T as TranscriptWord, o as buildBroadcastCdnUrl, p as buildBroadcastS3KeyPrefix, n as formatTime, u as useDialtribe } from './dialtribe-player-Rc9kfQiX.mjs';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
@@ -0,0 +1,3 @@
1
+ export { A as ApiClientConfig, h as AudioWaveform, B as Broadcast, C as CDN_DOMAIN, d as DIALTRIBE_API_BASE, c as DialtribeClient, a as DialtribeContextValue, i as DialtribeOverlay, k as DialtribeOverlayMode, j as DialtribeOverlayProps, e as DialtribePlayer, g as DialtribePlayerErrorBoundary, f as DialtribePlayerProps, D as DialtribeProvider, b as DialtribeProviderProps, E as ENDPOINTS, H as HTTP_STATUS, q as HttpStatusCode, L as LoadingSpinner, m as TranscriptData, l as TranscriptSegment, T as TranscriptWord, o as buildBroadcastCdnUrl, p as buildBroadcastS3KeyPrefix, n as formatTime, u as useDialtribe } from './dialtribe-player-Rc9kfQiX.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
@@ -8,9 +8,9 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
9
  var ReactPlayer__default = /*#__PURE__*/_interopDefault(ReactPlayer);
10
10
 
11
- // src/context/DialTribeProvider.tsx
12
- var DialTribeContext = react.createContext(null);
13
- function DialTribeProvider({
11
+ // src/context/DialtribeProvider.tsx
12
+ var DialtribeContext = react.createContext(null);
13
+ function DialtribeProvider({
14
14
  sessionToken: initialToken,
15
15
  onTokenRefresh,
16
16
  onTokenExpired,
@@ -46,19 +46,19 @@ function DialTribeProvider({
46
46
  markExpired,
47
47
  apiBaseUrl
48
48
  };
49
- return /* @__PURE__ */ jsxRuntime.jsx(DialTribeContext.Provider, { value, children });
49
+ return /* @__PURE__ */ jsxRuntime.jsx(DialtribeContext.Provider, { value, children });
50
50
  }
51
- function useDialTribe() {
52
- const context = react.useContext(DialTribeContext);
51
+ function useDialtribe() {
52
+ const context = react.useContext(DialtribeContext);
53
53
  if (!context) {
54
54
  throw new Error(
55
- 'useDialTribe must be used within a DialTribeProvider. Wrap your app with <DialTribeProvider sessionToken="sess_xxx">...</DialTribeProvider>'
55
+ 'useDialtribe must be used within a DialtribeProvider. Wrap your app with <DialtribeProvider sessionToken="sess_xxx">...</DialtribeProvider>'
56
56
  );
57
57
  }
58
58
  return context;
59
59
  }
60
60
 
61
- // src/client/DialTribeClient.ts
61
+ // src/client/DialtribeClient.ts
62
62
  function getDefaultApiBaseUrl() {
63
63
  if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DIALTRIBE_API_URL) {
64
64
  return process.env.NEXT_PUBLIC_DIALTRIBE_API_URL;
@@ -72,18 +72,19 @@ function getEndpoints(baseUrl = DIALTRIBE_API_BASE) {
72
72
  broadcast: (id) => `${baseUrl}/broadcasts/${id}`,
73
73
  contentPlay: `${baseUrl}/content/play`,
74
74
  presignedUrl: `${baseUrl}/media/presigned-url`,
75
- sessionStart: `${baseUrl}/session/start`,
76
- sessionPing: `${baseUrl}/session/ping`
75
+ audienceStart: `${baseUrl}/audiences/start`,
76
+ audiencePing: `${baseUrl}/audiences/ping`,
77
+ sessionPing: `${baseUrl}/sessions/ping`
77
78
  };
78
79
  }
79
80
  var ENDPOINTS = getEndpoints();
80
- var DialTribeClient = class {
81
+ var DialtribeClient = class {
81
82
  constructor(config) {
82
83
  this.config = config;
83
84
  this.endpoints = config.apiBaseUrl ? getEndpoints(config.apiBaseUrl) : ENDPOINTS;
84
85
  }
85
86
  /**
86
- * Make an authenticated request to DialTribe API
87
+ * Make an authenticated request to Dialtribe API
87
88
  *
88
89
  * Automatically:
89
90
  * - Adds Authorization header with session token
@@ -197,7 +198,7 @@ var DialTribeClient = class {
197
198
  * @returns audienceId and optional resumePosition
198
199
  */
199
200
  async startSession(params) {
200
- const response = await this.fetch(this.endpoints.sessionStart, {
201
+ const response = await this.fetch(this.endpoints.audienceStart, {
201
202
  method: "POST",
202
203
  body: JSON.stringify(params)
203
204
  });
@@ -216,7 +217,7 @@ var DialTribeClient = class {
216
217
  * - 3: UNMOUNT
217
218
  */
218
219
  async sendSessionPing(params) {
219
- const response = await this.fetch(this.endpoints.sessionPing, {
220
+ const response = await this.fetch(this.endpoints.audiencePing, {
220
221
  method: "POST",
221
222
  body: JSON.stringify(params)
222
223
  });
@@ -748,7 +749,7 @@ function getErrorMessage(error) {
748
749
  }
749
750
  return "Unable to play media. Please try refreshing the page or contact support if the problem persists.";
750
751
  }
751
- function BroadcastPlayer({
752
+ function DialtribePlayer({
752
753
  broadcast,
753
754
  appId,
754
755
  contentId,
@@ -759,18 +760,18 @@ function BroadcastPlayer({
759
760
  className = "",
760
761
  enableKeyboardShortcuts = false
761
762
  }) {
762
- const { sessionToken, setSessionToken, markExpired, apiBaseUrl } = useDialTribe();
763
+ const { sessionToken, setSessionToken, markExpired, apiBaseUrl } = useDialtribe();
763
764
  const clientRef = react.useRef(null);
764
765
  if (!clientRef.current && sessionToken) {
765
- clientRef.current = new DialTribeClient({
766
+ clientRef.current = new DialtribeClient({
766
767
  sessionToken,
767
768
  apiBaseUrl,
768
769
  onTokenRefresh: (newToken, expiresAt) => {
769
- debug.log(`[DialTribeClient] Token refreshed, expires at ${expiresAt}`);
770
+ debug.log(`[DialtribeClient] Token refreshed, expires at ${expiresAt}`);
770
771
  setSessionToken(newToken, expiresAt);
771
772
  },
772
773
  onTokenExpired: () => {
773
- debug.error("[DialTribeClient] Token expired");
774
+ debug.error("[DialtribeClient] Token expired");
774
775
  markExpired();
775
776
  }
776
777
  });
@@ -1215,7 +1216,7 @@ function BroadcastPlayer({
1215
1216
  setAudioElement(internalPlayer);
1216
1217
  }
1217
1218
  } catch (error) {
1218
- debug.error("[BroadcastPlayer] Error getting internal player:", error);
1219
+ debug.error("[DialtribePlayer] Error getting internal player:", error);
1219
1220
  }
1220
1221
  };
1221
1222
  react.useEffect(() => {
@@ -1423,7 +1424,7 @@ function BroadcastPlayer({
1423
1424
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { variant: "white", text: "Loading..." }) });
1424
1425
  }
1425
1426
  const hasTranscript = broadcast.transcriptStatus === 2 && transcriptData && (transcriptData.segments && transcriptData.segments.some((s) => s.words && s.words.length > 0) || transcriptData.words && transcriptData.words.length > 0);
1426
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-black rounded-lg shadow-2xl w-full max-h-full flex flex-col overflow-hidden ${className}`, children: [
1427
+ const playerContent = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-black rounded-lg shadow-2xl w-full max-h-full flex flex-col overflow-hidden ${className}`, children: [
1427
1428
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-zinc-900/50 backdrop-blur-sm border-b border-zinc-800 px-3 sm:px-4 md:px-6 py-2 sm:py-3 md:py-4 flex justify-between items-center rounded-t-lg shrink-0", children: [
1428
1429
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1429
1430
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-white", children: broadcast.streamKeyRecord?.foreignName || "Broadcast" }),
@@ -1955,90 +1956,9 @@ function BroadcastPlayer({
1955
1956
  }
1956
1957
  ` })
1957
1958
  ] });
1959
+ return playerContent;
1958
1960
  }
1959
- function BroadcastPlayerModal({
1960
- broadcast,
1961
- isOpen,
1962
- onClose,
1963
- appId,
1964
- contentId,
1965
- foreignId,
1966
- foreignTier,
1967
- renderClipCreator,
1968
- className,
1969
- enableKeyboardShortcuts = false
1970
- }) {
1971
- const closeButtonRef = react.useRef(null);
1972
- const previousActiveElement = react.useRef(null);
1973
- react.useEffect(() => {
1974
- if (!isOpen) return;
1975
- previousActiveElement.current = document.activeElement;
1976
- setTimeout(() => {
1977
- closeButtonRef.current?.focus();
1978
- }, 100);
1979
- return () => {
1980
- if (previousActiveElement.current) {
1981
- previousActiveElement.current.focus();
1982
- }
1983
- };
1984
- }, [isOpen]);
1985
- react.useEffect(() => {
1986
- if (!isOpen) return;
1987
- const handleKeyDown = (e) => {
1988
- if (e.key === "Escape") {
1989
- onClose();
1990
- }
1991
- };
1992
- document.addEventListener("keydown", handleKeyDown);
1993
- return () => document.removeEventListener("keydown", handleKeyDown);
1994
- }, [isOpen, onClose]);
1995
- if (!isOpen) return null;
1996
- const handleBackdropClick = (e) => {
1997
- if (e.target === e.currentTarget) {
1998
- onClose();
1999
- }
2000
- };
2001
- return /* @__PURE__ */ jsxRuntime.jsx(
2002
- "div",
2003
- {
2004
- className: "fixed inset-0 bg-black/70 backdrop-blur-xl flex items-center justify-center z-50 p-2 sm:p-4",
2005
- onClick: handleBackdropClick,
2006
- role: "dialog",
2007
- "aria-modal": "true",
2008
- "aria-label": "Broadcast player",
2009
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-7xl max-h-[95vh] sm:max-h-[90vh] overflow-hidden", children: [
2010
- /* @__PURE__ */ jsxRuntime.jsx(
2011
- "button",
2012
- {
2013
- ref: closeButtonRef,
2014
- onClick: onClose,
2015
- className: "absolute top-2 right-2 sm:top-4 sm:right-4 z-10 text-gray-400 hover:text-white text-2xl leading-none transition-colors w-8 h-8 flex items-center justify-center bg-black/50 rounded-full",
2016
- title: "Close (ESC)",
2017
- "aria-label": "Close player",
2018
- children: "\xD7"
2019
- }
2020
- ),
2021
- /* @__PURE__ */ jsxRuntime.jsx(
2022
- BroadcastPlayer,
2023
- {
2024
- broadcast,
2025
- appId,
2026
- contentId,
2027
- foreignId,
2028
- foreignTier,
2029
- renderClipCreator,
2030
- className,
2031
- enableKeyboardShortcuts,
2032
- onError: (error) => {
2033
- debug.error("[BroadcastPlayerModal] Player error:", error);
2034
- }
2035
- }
2036
- )
2037
- ] })
2038
- }
2039
- );
2040
- }
2041
- var BroadcastPlayerErrorBoundary = class extends react.Component {
1961
+ var DialtribePlayerErrorBoundary = class extends react.Component {
2042
1962
  constructor(props) {
2043
1963
  super(props);
2044
1964
  this.handleReset = () => {
@@ -2164,21 +2084,99 @@ var BroadcastPlayerErrorBoundary = class extends react.Component {
2164
2084
  return this.props.children;
2165
2085
  }
2166
2086
  };
2087
+ var overlayStyles = {
2088
+ modal: {
2089
+ backdrop: "bg-black/70 backdrop-blur-xl p-2 sm:p-4",
2090
+ container: "max-w-7xl max-h-[95vh] sm:max-h-[90vh]"
2091
+ },
2092
+ fullscreen: {
2093
+ backdrop: "bg-black",
2094
+ container: "h-full"
2095
+ }
2096
+ };
2097
+ function DialtribeOverlay({
2098
+ isOpen,
2099
+ onClose,
2100
+ mode = "modal",
2101
+ children,
2102
+ ariaLabel = "Dialog",
2103
+ showCloseButton = true,
2104
+ closeOnBackdropClick = true,
2105
+ closeOnEsc = true
2106
+ }) {
2107
+ const closeButtonRef = react.useRef(null);
2108
+ const previousActiveElement = react.useRef(null);
2109
+ react.useEffect(() => {
2110
+ if (!isOpen) return;
2111
+ previousActiveElement.current = document.activeElement;
2112
+ setTimeout(() => {
2113
+ closeButtonRef.current?.focus();
2114
+ }, 100);
2115
+ return () => {
2116
+ if (previousActiveElement.current) {
2117
+ previousActiveElement.current.focus();
2118
+ }
2119
+ };
2120
+ }, [isOpen]);
2121
+ react.useEffect(() => {
2122
+ if (!isOpen || !closeOnEsc) return;
2123
+ const handleKeyDown = (e) => {
2124
+ if (e.key === "Escape") {
2125
+ onClose();
2126
+ }
2127
+ };
2128
+ document.addEventListener("keydown", handleKeyDown);
2129
+ return () => document.removeEventListener("keydown", handleKeyDown);
2130
+ }, [isOpen, onClose, closeOnEsc]);
2131
+ if (!isOpen) {
2132
+ return null;
2133
+ }
2134
+ const handleBackdropClick = (e) => {
2135
+ if (closeOnBackdropClick && e.target === e.currentTarget) {
2136
+ onClose();
2137
+ }
2138
+ };
2139
+ const styles = overlayStyles[mode];
2140
+ return /* @__PURE__ */ jsxRuntime.jsx(
2141
+ "div",
2142
+ {
2143
+ className: `fixed inset-0 flex items-center justify-center z-50 ${styles.backdrop}`,
2144
+ onClick: handleBackdropClick,
2145
+ role: "dialog",
2146
+ "aria-modal": "true",
2147
+ "aria-label": ariaLabel,
2148
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative w-full overflow-hidden ${styles.container}`, children: [
2149
+ showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
2150
+ "button",
2151
+ {
2152
+ ref: closeButtonRef,
2153
+ onClick: onClose,
2154
+ className: "absolute top-2 right-2 sm:top-4 sm:right-4 z-10 text-gray-400 hover:text-white text-2xl leading-none transition-colors w-8 h-8 flex items-center justify-center bg-black/50 rounded-full",
2155
+ title: "Close (ESC)",
2156
+ "aria-label": "Close",
2157
+ children: "\xD7"
2158
+ }
2159
+ ),
2160
+ children
2161
+ ] })
2162
+ }
2163
+ );
2164
+ }
2167
2165
 
2168
2166
  exports.AudioWaveform = AudioWaveform;
2169
- exports.BroadcastPlayer = BroadcastPlayer;
2170
- exports.BroadcastPlayerErrorBoundary = BroadcastPlayerErrorBoundary;
2171
- exports.BroadcastPlayerModal = BroadcastPlayerModal;
2172
2167
  exports.CDN_DOMAIN = CDN_DOMAIN;
2173
2168
  exports.DIALTRIBE_API_BASE = DIALTRIBE_API_BASE;
2174
- exports.DialTribeClient = DialTribeClient;
2175
- exports.DialTribeProvider = DialTribeProvider;
2169
+ exports.DialtribeClient = DialtribeClient;
2170
+ exports.DialtribeOverlay = DialtribeOverlay;
2171
+ exports.DialtribePlayer = DialtribePlayer;
2172
+ exports.DialtribePlayerErrorBoundary = DialtribePlayerErrorBoundary;
2173
+ exports.DialtribeProvider = DialtribeProvider;
2176
2174
  exports.ENDPOINTS = ENDPOINTS;
2177
2175
  exports.HTTP_STATUS = HTTP_STATUS;
2178
2176
  exports.LoadingSpinner = LoadingSpinner;
2179
2177
  exports.buildBroadcastCdnUrl = buildBroadcastCdnUrl;
2180
2178
  exports.buildBroadcastS3KeyPrefix = buildBroadcastS3KeyPrefix;
2181
2179
  exports.formatTime = formatTime;
2182
- exports.useDialTribe = useDialTribe;
2183
- //# sourceMappingURL=broadcast-player.js.map
2184
- //# sourceMappingURL=broadcast-player.js.map
2180
+ exports.useDialtribe = useDialtribe;
2181
+ //# sourceMappingURL=dialtribe-player.js.map
2182
+ //# sourceMappingURL=dialtribe-player.js.map