@sesionario/blocks 1.12.0 → 1.13.1

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.cts CHANGED
@@ -431,7 +431,7 @@ declare function insertAtCaret(element: {
431
431
  */
432
432
  type HlsPlayerMode = "live" | "vod";
433
433
  /** Coarse category the player uses to pick the right localized message. */
434
- type PlaybackErrorKind = "unavailable" | "network" | "media" | "unsupported" | "generic";
434
+ type PlaybackErrorKind = "unavailable" | "network" | "media" | "unsupported" | "resync" | "generic";
435
435
  type PlaybackErrorContext = {
436
436
  mode: HlsPlayerMode;
437
437
  src: string;
@@ -481,6 +481,15 @@ type DescribedPlaybackError = {
481
481
  kind: PlaybackErrorKind;
482
482
  detail: PlaybackErrorDetail;
483
483
  };
484
+ /**
485
+ * Soft (non-fatal) report for an automatic A/V resync. Apps should treat this
486
+ * like other non-fatal playback events (breadcrumb / warn), never as a hard
487
+ * error UI — the player recovers in place.
488
+ */
489
+ declare function describeAvResync(input: {
490
+ lagSeconds: number;
491
+ context: PlaybackErrorContext;
492
+ }): DescribedPlaybackError;
484
493
  declare function describePlaybackError(input: DescribePlaybackErrorInput): DescribedPlaybackError;
485
494
 
486
495
  interface PlaybackStats {
@@ -1095,6 +1104,30 @@ type UseSupportConversationResult = {
1095
1104
  };
1096
1105
  declare function useSupportConversation({ client, getWsUrl, conversationId: conversationIdProp, open, enabled, onConversationReady, onIncomingMessage, }: UseSupportConversationOptions): UseSupportConversationResult;
1097
1106
 
1107
+ type RealtimeEvent = {
1108
+ type: string;
1109
+ payload: unknown;
1110
+ ts: number;
1111
+ };
1112
+ type UseRealtimeChannelOptions = {
1113
+ /**
1114
+ * Resolve a WebSocket URL (including auth token). Return null to skip.
1115
+ * Called on each (re)connect so tokens can be refreshed.
1116
+ */
1117
+ getWsUrl: () => Promise<string | null>;
1118
+ /** Called for every server event (invalidation hints). */
1119
+ onEvent: (event: RealtimeEvent) => void;
1120
+ enabled?: boolean;
1121
+ /** Base reconnect delay in ms (exponential backoff capped at 30s). */
1122
+ reconnectDelayMs?: number;
1123
+ };
1124
+ /**
1125
+ * Subscribe to a realtime-svc channel WebSocket.
1126
+ * Reconnects with exponential backoff; refreshes the URL (token) on each attempt.
1127
+ * Treats events as invalidation signals — callers should re-fetch authoritative data.
1128
+ */
1129
+ declare function useRealtimeChannel({ getWsUrl, onEvent, enabled, reconnectDelayMs, }: UseRealtimeChannelOptions): void;
1130
+
1098
1131
  declare function cn(...inputs: ClassValue[]): string;
1099
1132
 
1100
- export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type ConversationKind, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, ExpandableText, type ExpandableTextProps, type FeatureEntry, type FindOrCreateConversationInput, type HlsPlayerMode, ImageLightbox, type ImageLightboxLabels, type ImageLightboxProps, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, type MessageComposerProps, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, type OpenThreadRequest, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, SearchablePicker, type SearchablePickerCreateOption, type SearchablePickerLabels, type SearchablePickerMultipleProps, type SearchablePickerPinned, type SearchablePickerProps, type SearchablePickerSingleProps, type SupportChatClient, type SupportConversation, type SupportMessage, type SupportMessengerItem, type SupportMessengerLabels, SupportMessengerProvider, type SupportMessengerProviderProps, type SupportMessengerTab, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, type UseSupportConversationOptions, type UseSupportConversationResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery, usePlaybackStats, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
1133
+ export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type ConversationKind, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, ExpandableText, type ExpandableTextProps, type FeatureEntry, type FindOrCreateConversationInput, type HlsPlayerMode, ImageLightbox, type ImageLightboxLabels, type ImageLightboxProps, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, type MessageComposerProps, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, type OpenThreadRequest, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, type RealtimeEvent, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, SearchablePicker, type SearchablePickerCreateOption, type SearchablePickerLabels, type SearchablePickerMultipleProps, type SearchablePickerPinned, type SearchablePickerProps, type SearchablePickerSingleProps, type SupportChatClient, type SupportConversation, type SupportMessage, type SupportMessengerItem, type SupportMessengerLabels, SupportMessengerProvider, type SupportMessengerProviderProps, type SupportMessengerTab, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseRealtimeChannelOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, type UseSupportConversationOptions, type UseSupportConversationResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describeAvResync, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery, usePlaybackStats, useRealtimeChannel, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
package/dist/index.d.ts CHANGED
@@ -431,7 +431,7 @@ declare function insertAtCaret(element: {
431
431
  */
432
432
  type HlsPlayerMode = "live" | "vod";
433
433
  /** Coarse category the player uses to pick the right localized message. */
434
- type PlaybackErrorKind = "unavailable" | "network" | "media" | "unsupported" | "generic";
434
+ type PlaybackErrorKind = "unavailable" | "network" | "media" | "unsupported" | "resync" | "generic";
435
435
  type PlaybackErrorContext = {
436
436
  mode: HlsPlayerMode;
437
437
  src: string;
@@ -481,6 +481,15 @@ type DescribedPlaybackError = {
481
481
  kind: PlaybackErrorKind;
482
482
  detail: PlaybackErrorDetail;
483
483
  };
484
+ /**
485
+ * Soft (non-fatal) report for an automatic A/V resync. Apps should treat this
486
+ * like other non-fatal playback events (breadcrumb / warn), never as a hard
487
+ * error UI — the player recovers in place.
488
+ */
489
+ declare function describeAvResync(input: {
490
+ lagSeconds: number;
491
+ context: PlaybackErrorContext;
492
+ }): DescribedPlaybackError;
484
493
  declare function describePlaybackError(input: DescribePlaybackErrorInput): DescribedPlaybackError;
485
494
 
486
495
  interface PlaybackStats {
@@ -1095,6 +1104,30 @@ type UseSupportConversationResult = {
1095
1104
  };
1096
1105
  declare function useSupportConversation({ client, getWsUrl, conversationId: conversationIdProp, open, enabled, onConversationReady, onIncomingMessage, }: UseSupportConversationOptions): UseSupportConversationResult;
1097
1106
 
1107
+ type RealtimeEvent = {
1108
+ type: string;
1109
+ payload: unknown;
1110
+ ts: number;
1111
+ };
1112
+ type UseRealtimeChannelOptions = {
1113
+ /**
1114
+ * Resolve a WebSocket URL (including auth token). Return null to skip.
1115
+ * Called on each (re)connect so tokens can be refreshed.
1116
+ */
1117
+ getWsUrl: () => Promise<string | null>;
1118
+ /** Called for every server event (invalidation hints). */
1119
+ onEvent: (event: RealtimeEvent) => void;
1120
+ enabled?: boolean;
1121
+ /** Base reconnect delay in ms (exponential backoff capped at 30s). */
1122
+ reconnectDelayMs?: number;
1123
+ };
1124
+ /**
1125
+ * Subscribe to a realtime-svc channel WebSocket.
1126
+ * Reconnects with exponential backoff; refreshes the URL (token) on each attempt.
1127
+ * Treats events as invalidation signals — callers should re-fetch authoritative data.
1128
+ */
1129
+ declare function useRealtimeChannel({ getWsUrl, onEvent, enabled, reconnectDelayMs, }: UseRealtimeChannelOptions): void;
1130
+
1098
1131
  declare function cn(...inputs: ClassValue[]): string;
1099
1132
 
1100
- export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type ConversationKind, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, ExpandableText, type ExpandableTextProps, type FeatureEntry, type FindOrCreateConversationInput, type HlsPlayerMode, ImageLightbox, type ImageLightboxLabels, type ImageLightboxProps, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, type MessageComposerProps, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, type OpenThreadRequest, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, SearchablePicker, type SearchablePickerCreateOption, type SearchablePickerLabels, type SearchablePickerMultipleProps, type SearchablePickerPinned, type SearchablePickerProps, type SearchablePickerSingleProps, type SupportChatClient, type SupportConversation, type SupportMessage, type SupportMessengerItem, type SupportMessengerLabels, SupportMessengerProvider, type SupportMessengerProviderProps, type SupportMessengerTab, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, type UseSupportConversationOptions, type UseSupportConversationResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery, usePlaybackStats, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
1133
+ export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type ConversationKind, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, ExpandableText, type ExpandableTextProps, type FeatureEntry, type FindOrCreateConversationInput, type HlsPlayerMode, ImageLightbox, type ImageLightboxLabels, type ImageLightboxProps, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, type MessageComposerProps, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, type OpenThreadRequest, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, type RealtimeEvent, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, SearchablePicker, type SearchablePickerCreateOption, type SearchablePickerLabels, type SearchablePickerMultipleProps, type SearchablePickerPinned, type SearchablePickerProps, type SearchablePickerSingleProps, type SupportChatClient, type SupportConversation, type SupportMessage, type SupportMessengerItem, type SupportMessengerLabels, SupportMessengerProvider, type SupportMessengerProviderProps, type SupportMessengerTab, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseRealtimeChannelOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, type UseSupportConversationOptions, type UseSupportConversationResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describeAvResync, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery, usePlaybackStats, useRealtimeChannel, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
package/dist/index.js CHANGED
@@ -3431,6 +3431,20 @@ function kindForNative(input) {
3431
3431
  if (code === MEDIA_ERR_NETWORK) return "unavailable";
3432
3432
  return "generic";
3433
3433
  }
3434
+ function describeAvResync(input) {
3435
+ const lag = Number.isFinite(input.lagSeconds) ? input.lagSeconds : 0;
3436
+ return {
3437
+ summary: `av-resync lag=${lag.toFixed(3)}s (non-fatal)`,
3438
+ kind: "resync",
3439
+ detail: {
3440
+ source: input.context.source,
3441
+ kind: "resync",
3442
+ fatal: false,
3443
+ reason: `presented frame lag ${lag.toFixed(3)}s`,
3444
+ context: input.context
3445
+ }
3446
+ };
3447
+ }
3434
3448
  function describePlaybackError(input) {
3435
3449
  if (input.source === "unsupported") {
3436
3450
  return {
@@ -3489,6 +3503,10 @@ function describePlaybackError(input) {
3489
3503
  // src/components/video/useHlsPlayback.ts
3490
3504
  var RETRY_INTERVAL_MS = 3e3;
3491
3505
  var MAX_MEDIA_ERROR_RETRIES = 5;
3506
+ var DRIFT_THRESHOLD_S = 0.4;
3507
+ var DRIFT_CONSECUTIVE_SAMPLES = 3;
3508
+ var RESYNC_COOLDOWN_MS = 1e4;
3509
+ var LIVE_EDGE_RESYNC_THRESHOLD_S = 8;
3492
3510
  function useHlsPlayback({
3493
3511
  src,
3494
3512
  mode,
@@ -3528,6 +3546,7 @@ function useHlsPlayback({
3528
3546
  let retryTimer = null;
3529
3547
  let manifestParsed = false;
3530
3548
  let mediaErrorRetries = 0;
3549
+ let playbackSource = "hls";
3531
3550
  const teardown = [];
3532
3551
  media.muted = muted;
3533
3552
  setState("loading");
@@ -3536,7 +3555,13 @@ function useHlsPlayback({
3536
3555
  setQualities([]);
3537
3556
  setActiveLevel(-1);
3538
3557
  function baseContext() {
3539
- return { mode, src, manifestParsed, retryCount: mediaErrorRetries };
3558
+ return {
3559
+ mode,
3560
+ src,
3561
+ manifestParsed,
3562
+ retryCount: mediaErrorRetries,
3563
+ source: playbackSource
3564
+ };
3540
3565
  }
3541
3566
  function clearRetryTimer() {
3542
3567
  if (retryTimer !== null) {
@@ -3575,6 +3600,53 @@ function useHlsPlayback({
3575
3600
  if (!cancelled) retryFn();
3576
3601
  }, RETRY_INTERVAL_MS);
3577
3602
  }
3603
+ function startDriftWatchdog(el) {
3604
+ if (typeof el.requestVideoFrameCallback !== "function") return;
3605
+ let consecutiveLagSamples = 0;
3606
+ let lastResyncAt = 0;
3607
+ let handle = null;
3608
+ const tick = (_now, metadata) => {
3609
+ if (cancelled) return;
3610
+ handle = el.requestVideoFrameCallback(tick);
3611
+ if (el.paused || el.ended) {
3612
+ consecutiveLagSamples = 0;
3613
+ return;
3614
+ }
3615
+ const lag = el.currentTime - metadata.mediaTime;
3616
+ if (!(lag > DRIFT_THRESHOLD_S)) {
3617
+ consecutiveLagSamples = 0;
3618
+ return;
3619
+ }
3620
+ consecutiveLagSamples += 1;
3621
+ if (consecutiveLagSamples < DRIFT_CONSECUTIVE_SAMPLES) return;
3622
+ const nowMs = performance.now();
3623
+ if (nowMs - lastResyncAt < RESYNC_COOLDOWN_MS) return;
3624
+ lastResyncAt = nowMs;
3625
+ consecutiveLagSamples = 0;
3626
+ if (mode === "live" && el.seekable.length > 0) {
3627
+ const edge = el.seekable.end(el.seekable.length - 1);
3628
+ if (edge - el.currentTime > LIVE_EDGE_RESYNC_THRESHOLD_S) {
3629
+ el.currentTime = edge;
3630
+ } else {
3631
+ el.currentTime = el.currentTime + 1e-3;
3632
+ }
3633
+ } else {
3634
+ el.currentTime = el.currentTime + 1e-3;
3635
+ }
3636
+ onErrorRef.current?.(
3637
+ describeAvResync({
3638
+ lagSeconds: lag,
3639
+ context: baseContext()
3640
+ })
3641
+ );
3642
+ };
3643
+ handle = el.requestVideoFrameCallback(tick);
3644
+ teardown.push(() => {
3645
+ if (handle != null && typeof el.cancelVideoFrameCallback === "function") {
3646
+ el.cancelVideoFrameCallback(handle);
3647
+ }
3648
+ });
3649
+ }
3578
3650
  function onPlaying() {
3579
3651
  manifestParsed = true;
3580
3652
  mediaErrorRetries = 0;
@@ -3593,7 +3665,9 @@ function useHlsPlayback({
3593
3665
  media.removeEventListener("pause", onPaused);
3594
3666
  media.removeEventListener("ended", onPaused);
3595
3667
  });
3668
+ startDriftWatchdog(media);
3596
3669
  function initNative() {
3670
+ playbackSource = "native";
3597
3671
  manifestParsed = false;
3598
3672
  media.removeAttribute("src");
3599
3673
  media.load();
@@ -3609,7 +3683,7 @@ function useHlsPlayback({
3609
3683
  reportFatal({
3610
3684
  source: "native",
3611
3685
  mediaError: media.error,
3612
- context: { ...baseContext(), source: "native" }
3686
+ context: baseContext()
3613
3687
  });
3614
3688
  return;
3615
3689
  }
@@ -3617,7 +3691,7 @@ function useHlsPlayback({
3617
3691
  describePlaybackError({
3618
3692
  source: "native",
3619
3693
  mediaError: media.error,
3620
- context: { ...baseContext(), source: "native" }
3694
+ context: baseContext()
3621
3695
  })
3622
3696
  );
3623
3697
  scheduleRetry(() => {
@@ -3633,6 +3707,7 @@ function useHlsPlayback({
3633
3707
  });
3634
3708
  }
3635
3709
  function initHlsJs(Hls) {
3710
+ playbackSource = "hls";
3636
3711
  destroyHls();
3637
3712
  manifestParsed = false;
3638
3713
  const config = mode === "live" ? createLiveHlsConfig() : createVodHlsConfig();
@@ -3664,7 +3739,7 @@ function useHlsPlayback({
3664
3739
  response: data.response,
3665
3740
  reason: data.reason,
3666
3741
  error: data.error,
3667
- context: { ...baseContext(), source: "hls" }
3742
+ context: baseContext()
3668
3743
  })
3669
3744
  );
3670
3745
  if (!data.fatal) return;
@@ -3699,7 +3774,7 @@ function useHlsPlayback({
3699
3774
  response: data.response,
3700
3775
  reason: data.reason,
3701
3776
  error: data.error,
3702
- context: { ...baseContext(), source: "hls" }
3777
+ context: baseContext()
3703
3778
  });
3704
3779
  });
3705
3780
  }
@@ -3716,9 +3791,10 @@ function useHlsPlayback({
3716
3791
  } else if (media.canPlayType("application/vnd.apple.mpegurl")) {
3717
3792
  initNative();
3718
3793
  } else {
3794
+ playbackSource = "unsupported";
3719
3795
  reportFatal({
3720
3796
  source: "unsupported",
3721
- context: { ...baseContext(), source: "unsupported" }
3797
+ context: baseContext()
3722
3798
  });
3723
3799
  }
3724
3800
  }
@@ -4065,6 +4141,8 @@ function VideoPlayer({
4065
4141
  return t.errorMedia;
4066
4142
  case "unsupported":
4067
4143
  return t.errorUnsupported;
4144
+ case "resync":
4145
+ return t.errorMedia;
4068
4146
  case "generic":
4069
4147
  return t.errorGeneric;
4070
4148
  default: {
@@ -6076,7 +6154,7 @@ function MessageScrollerButton({
6076
6154
  "data-size": size,
6077
6155
  direction,
6078
6156
  className: cn(
6079
- "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",
6157
+ "absolute left-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full data-[direction=start]:[&_svg]:rotate-180",
6080
6158
  className
6081
6159
  ),
6082
6160
  render: render ?? /* @__PURE__ */ jsx(Button, { variant, size }),
@@ -6874,7 +6952,106 @@ function createSupportChatClient(basePath = "/api/chat-svc") {
6874
6952
  }
6875
6953
  };
6876
6954
  }
6955
+ var DEFAULT_RECONNECT_MS = 2e3;
6956
+ var MAX_RECONNECT_MS = 3e4;
6957
+ function useRealtimeChannel({
6958
+ getWsUrl,
6959
+ onEvent,
6960
+ enabled = true,
6961
+ reconnectDelayMs = DEFAULT_RECONNECT_MS
6962
+ }) {
6963
+ const onEventRef = useRef(onEvent);
6964
+ onEventRef.current = onEvent;
6965
+ const getWsUrlRef = useRef(getWsUrl);
6966
+ getWsUrlRef.current = getWsUrl;
6967
+ useEffect(() => {
6968
+ if (!enabled) return;
6969
+ let cancelled = false;
6970
+ let socket = null;
6971
+ let reconnectTimer = null;
6972
+ let attempt = 0;
6973
+ const connectGen = { current: 0 };
6974
+ const clearReconnect = () => {
6975
+ if (reconnectTimer) {
6976
+ clearTimeout(reconnectTimer);
6977
+ reconnectTimer = null;
6978
+ }
6979
+ };
6980
+ const scheduleReconnect = () => {
6981
+ if (cancelled) return;
6982
+ clearReconnect();
6983
+ const delay = Math.min(reconnectDelayMs * 2 ** attempt, MAX_RECONNECT_MS);
6984
+ attempt += 1;
6985
+ reconnectTimer = setTimeout(() => {
6986
+ void connect();
6987
+ }, delay);
6988
+ };
6989
+ const connect = async () => {
6990
+ const gen = ++connectGen.current;
6991
+ clearReconnect();
6992
+ const url = await getWsUrlRef.current();
6993
+ if (cancelled || gen !== connectGen.current) return;
6994
+ if (!url) {
6995
+ scheduleReconnect();
6996
+ return;
6997
+ }
6998
+ if (socket) {
6999
+ try {
7000
+ socket.close();
7001
+ } catch {
7002
+ }
7003
+ socket = null;
7004
+ }
7005
+ const ws = new WebSocket(url);
7006
+ socket = ws;
7007
+ ws.onopen = () => {
7008
+ if (cancelled || gen !== connectGen.current) return;
7009
+ attempt = 0;
7010
+ };
7011
+ ws.onmessage = (msg) => {
7012
+ if (cancelled || gen !== connectGen.current) return;
7013
+ let data;
7014
+ try {
7015
+ data = JSON.parse(String(msg.data));
7016
+ } catch {
7017
+ return;
7018
+ }
7019
+ if (typeof data?.type !== "string") return;
7020
+ if (data.type === "pong") return;
7021
+ onEventRef.current(data);
7022
+ };
7023
+ ws.onclose = () => {
7024
+ if (cancelled || gen !== connectGen.current) return;
7025
+ socket = null;
7026
+ scheduleReconnect();
7027
+ };
7028
+ ws.onerror = () => {
7029
+ };
7030
+ };
7031
+ const onVisibility = () => {
7032
+ if (document.visibilityState !== "visible" || cancelled) return;
7033
+ if (!socket || socket.readyState === WebSocket.CLOSED) {
7034
+ void connect();
7035
+ }
7036
+ };
7037
+ void connect();
7038
+ document.addEventListener("visibilitychange", onVisibility);
7039
+ return () => {
7040
+ cancelled = true;
7041
+ connectGen.current += 1;
7042
+ clearReconnect();
7043
+ document.removeEventListener("visibilitychange", onVisibility);
7044
+ if (socket) {
7045
+ try {
7046
+ socket.close();
7047
+ } catch {
7048
+ }
7049
+ socket = null;
7050
+ }
7051
+ };
7052
+ }, [enabled, reconnectDelayMs]);
7053
+ }
6877
7054
 
6878
- export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PhoneInput, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery2 as useMediaQuery, usePlaybackStats, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
7055
+ export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PhoneInput, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describeAvResync, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery2 as useMediaQuery, usePlaybackStats, useRealtimeChannel, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
6879
7056
  //# sourceMappingURL=index.js.map
6880
7057
  //# sourceMappingURL=index.js.map