@mottosports/motto-video-player 1.0.1-rc.14 → 1.0.1-rc.16

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
@@ -8,6 +8,7 @@ React video player component for the Motto platform, powered by Shaka Player wit
8
8
  - 🔄 **TanStack Query Integration**: Advanced caching, background refetching, and error handling
9
9
  - 📱 **Responsive Design**: Automatic aspect ratio handling and mobile-friendly controls
10
10
  - 🎮 **Skip Controls**: Built-in skip back/forward buttons with customizable durations
11
+ - ⌨️ **Keyboard Controls**: Desktop keyboard shortcuts (arrows for skip, spacebar for play/pause)
11
12
  - 🎯 **Quality Control**: Automatic quality selection and manual quality switching
12
13
  - 📊 **Analytics**: Built-in Mux analytics support
13
14
  - 🖥️ **Chromecast Support**: Cast videos to compatible devices
@@ -126,6 +127,16 @@ function MyPlayer() {
126
127
  />
127
128
  ```
128
129
 
130
+ ### Keyboard Controls
131
+
132
+ Desktop users can control the player using keyboard shortcuts:
133
+
134
+ - **←** Left Arrow: Skip back 15 seconds
135
+ - **→** Right Arrow: Skip forward 15 seconds
136
+ - **Space**: Play/Pause toggle
137
+
138
+ Keyboard controls are automatically enabled on desktop devices (disabled on mobile) and work when the player is focused or when no input fields are active.
139
+
129
140
  ### Responsive Sizing
130
141
 
131
142
  ```jsx
package/dist/index.js CHANGED
@@ -67,7 +67,7 @@ function styleInject(css, { insertAt } = {}) {
67
67
  styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wide: 0.025em;\n --tracking-widest: 0.1em;\n --radius-md: 0.375rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --aspect-video: 16 / 9;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-auto {\n pointer-events: auto;\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .z-10 {\n z-index: 10;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-6 {\n margin: calc(var(--spacing) * 6);\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-3 {\n margin-top: calc(var(--spacing) * 3);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .aspect-video {\n aspect-ratio: var(--aspect-video);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-12 {\n height: calc(var(--spacing) * 12);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-12 {\n width: calc(var(--spacing) * 12);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-full {\n width: 100%;\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .auto-cols-max {\n grid-auto-columns: max-content;\n }\n .grid-flow-col {\n grid-auto-flow: column;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-stretch {\n justify-content: stretch;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-5 {\n gap: calc(var(--spacing) * 5);\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .bg-\\[\\#151515\\] {\n background-color: #151515;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-t {\n --tw-gradient-position: to top in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black\\/70 {\n --tw-gradient-from: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-transparent {\n --tw-gradient-to: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .font-mono {\n font-family: var(--font-mono);\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-5xl {\n font-size: var(--text-5xl);\n line-height: var(--tw-leading, var(--text-5xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wide {\n --tw-tracking: var(--tracking-wide);\n letter-spacing: var(--tracking-wide);\n }\n .tracking-widest {\n --tw-tracking: var(--tracking-widest);\n letter-spacing: var(--tracking-widest);\n }\n .text-white {\n color: var(--color-white);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .md\\:rounded-2xl {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl);\n }\n }\n .md\\:rounded-2xl\\! {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl) !important;\n }\n }\n .md\\:text-base {\n @media (width >= 48rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .md\\:text-sm {\n @media (width >= 48rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:text-xl {\n @media (width >= 48rem) {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n}\n@layer components {\n .motto-video-container {\n position: relative;\n width: 100%;\n min-height: 300px;\n }\n @supports (aspect-ratio: 16/9) {\n .motto-video-container {\n min-height: auto;\n }\n }\n .motto-video-responsive {\n position: absolute;\n top: calc(var(--spacing) * 0);\n left: calc(var(--spacing) * 0);\n height: 100%;\n width: 100%;\n }\n .motto-skip-button {\n position: absolute;\n top: calc(1/2 * 100%);\n z-index: 10;\n display: flex;\n height: calc(var(--spacing) * 16);\n width: calc(var(--spacing) * 16);\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n color: var(--color-white);\n opacity: 80%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 110%;\n --tw-scale-y: 110%;\n --tw-scale-z: 110%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n &:hover {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .motto-skip-button-back {\n left: calc(var(--spacing) * 5);\n }\n .motto-skip-button-forward {\n right: calc(var(--spacing) * 5);\n }\n .motto-mobile-controls-overlay {\n position: absolute;\n inset: calc(var(--spacing) * 0);\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 300ms;\n transition-duration: 300ms;\n pointer-events: none;\n }\n .motto-mobile-controls-group {\n display: flex;\n align-items: center;\n gap: calc(var(--spacing) * 8);\n opacity: 100%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: none;\n }\n .motto-mobile-play-button {\n display: flex;\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-play-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-play-button svg {\n height: calc(var(--spacing) * 7);\n width: calc(var(--spacing) * 7);\n }\n .motto-mobile-skip-button {\n display: flex;\n height: calc(var(--spacing) * 10);\n width: calc(var(--spacing) * 10);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-skip-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-skip-button svg {\n height: calc(var(--spacing) * 6);\n width: calc(var(--spacing) * 6);\n }\n}\n@media (min-width: 768px) {\n .motto-mobile-controls-overlay {\n display: none !important;\n }\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-button[title*="Skip back"],\n .shaka-controls-container .shaka-button[title*="Skip forward"],\n .shaka-controls-container .shaka-button[aria-label*="Skip back"],\n .shaka-controls-container .shaka-button[aria-label*="Skip forward"],\n .shaka-controls-container button[title*="Skip back"],\n .shaka-controls-container button[title*="Skip forward"],\n .shaka-controls-container button[aria-label*="Skip back"],\n .shaka-controls-container button[aria-label*="Skip forward"],\n .motto-native-skip-button:not(.motto-mobile-skip-button),\n .motto-skip-back-button:not(.motto-mobile-skip-button),\n .motto-skip-forward-button:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button),\n button[title*="Skip back"]:not(.motto-mobile-skip-button),\n button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button) {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n width: 0 !important;\n height: 0 !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n .motto-mobile-skip-button {\n display: flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n.shaka-seek-bar-container {\n height: 6px !important;\n width: 100% !important;\n margin: 8px 0 !important;\n border-radius: 4px !important;\n position: relative !important;\n border-top: none !important;\n border-bottom: none !important;\n box-shadow: none !important;\n}\n.shaka-seek-bar {\n height: 6px !important;\n width: 100% !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n background: transparent !important;\n cursor: pointer !important;\n border: none !important;\n outline: none !important;\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n border-radius: 4px !important;\n}\n.shaka-seek-bar::-webkit-slider-runnable-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-moz-range-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-webkit-slider-thumb {\n -webkit-appearance: none !important;\n appearance: none !important;\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.shaka-seek-bar::-moz-range-thumb {\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.motto-skip-back-button,\n.motto-skip-forward-button,\n.motto-native-skip-button {\n background: transparent !important;\n border: none !important;\n padding: 4px !important;\n margin: 0px !important;\n cursor: pointer !important;\n color: #ffffff !important;\n transition: all 0.2s ease !important;\n min-width: 32px !important;\n height: 32px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n border-radius: 4px !important;\n width: 25px;\n}\n.motto-skip-back-button:hover,\n.motto-skip-forward-button:hover,\n.motto-native-skip-button:hover {\n opacity: 0.8 !important;\n background: transparent !important;\n transform: scale(1.05) !important;\n}\n.motto-skip-back-button:active,\n.motto-skip-forward-button:active,\n.motto-native-skip-button:active {\n transform: scale(0.95) !important;\n}\n.motto-skip-back-button svg,\n.motto-skip-forward-button svg,\n.motto-native-skip-button svg {\n width: 24px !important;\n height: 24px !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-play-button,\n .shaka-controls-container .shaka-pause-button {\n display: none !important;\n }\n}\n.shaka-spinner-svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-spinner-path {\n stroke: white !important;\n fill: none !important;\n}\n.shaka-spinner-container {\n color: white !important;\n}\n.shaka-buffering-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner path {\n stroke: white !important;\n fill: none !important;\n}\n[data-shaka-player-container] .shaka-spinner,\n[data-shaka-player-container] .spinner {\n color: white !important;\n border-color: white !important;\n}\n.material-icons.shaka-spinner {\n color: white !important;\n}\n.shaka-controls-container .shaka-spinner,\n.shaka-video-container .shaka-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner svg,\n.shaka-video-container .shaka-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner path,\n.shaka-video-container .shaka-spinner path {\n stroke: white !important;\n}\n.motto-video-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n linear-gradient(\n 135deg,\n #1a1a1a 0%,\n #2d2d2d 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: opacity 0.3s ease;\n}\n.motto-video-loading-overlay.hidden {\n opacity: 0;\n pointer-events: none;\n}\n.motto-video-loading-content {\n text-align: center;\n color: white;\n}\n.motto-video-loading-icon {\n width: 64px;\n height: 64px;\n margin-bottom: 16px;\n opacity: 0.7;\n}\n.motto-video-loading-text {\n font-size: 16px;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.motto-video-loading-subtext {\n font-size: 14px;\n opacity: 0.7;\n}\n@keyframes pulse-live {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n.shaka-play-button-container {\n display: none !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container {\n z-index: 90 !important;\n height: 100px !important;\n bottom: 0 !important;\n top: unset !important;\n }\n}\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-tracking { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-translate-x { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-y { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-z { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-border-style: solid;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
68
68
 
69
69
  // src/Player.tsx
70
- var import_react10 = require("react");
70
+ var import_react11 = require("react");
71
71
  var import_shaka_player4 = __toESM(require("shaka-player/dist/shaka-player.ui"));
72
72
 
73
73
  // src/hooks/useShakePlayer.ts
@@ -158,11 +158,25 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
158
158
  if (!playerRef.current) return;
159
159
  if (height === 0) {
160
160
  playerRef.current.configure({
161
- abr: { enabled: true }
161
+ abr: {
162
+ enabled: true,
163
+ switchInterval: 2,
164
+ // quicker re-checks
165
+ clearBufferSwitch: true,
166
+ safeMarginSwitch: 10
167
+ // leave ~10 s in front of the playhead }
168
+ }
162
169
  });
163
170
  } else {
164
171
  playerRef.current.configure({
165
- abr: { enabled: false }
172
+ abr: {
173
+ enabled: false,
174
+ switchInterval: 2,
175
+ // quicker re-checks
176
+ clearBufferSwitch: true,
177
+ safeMarginSwitch: 10
178
+ // leave ~10 s in front of the playhead }
179
+ }
166
180
  });
167
181
  const tracks = playerRef.current.getVariantTracks();
168
182
  const targetTrack = tracks.find((track) => track.height === height);
@@ -589,6 +603,7 @@ var MobileControlsContainerFactory = class {
589
603
  };
590
604
  var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
591
605
  const uiRef = (0, import_react5.useRef)(null);
606
+ const mobileOverlayRef = (0, import_react5.useRef)(null);
592
607
  const registeredElements = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
593
608
  const initializeUI = (0, import_react5.useCallback)(async () => {
594
609
  if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
@@ -660,7 +675,14 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
660
675
  const container = containerRef.current;
661
676
  const video = videoRef.current;
662
677
  if (container && video) {
663
- new MobileControlsContainer(container, { getVideo: () => video }, onSkipBack, onSkipForward);
678
+ if (!mobileOverlayRef.current) {
679
+ mobileOverlayRef.current = new MobileControlsContainer(
680
+ container,
681
+ { getVideo: () => video },
682
+ onSkipBack,
683
+ onSkipForward
684
+ );
685
+ }
664
686
  }
665
687
  }, 500);
666
688
  }
@@ -675,6 +697,14 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
675
697
  }
676
698
  uiRef.current = null;
677
699
  }
700
+ if (mobileOverlayRef.current) {
701
+ try {
702
+ mobileOverlayRef.current.release();
703
+ } catch (error) {
704
+ console.warn("Error releasing mobile controls overlay:", error);
705
+ }
706
+ mobileOverlayRef.current = null;
707
+ }
678
708
  }, []);
679
709
  return {
680
710
  uiRef,
@@ -859,12 +889,10 @@ var useLiveIndicator = (containerRef, options = {}) => {
859
889
  characterData: true,
860
890
  characterDataOldValue: true
861
891
  });
862
- const intervalId = setInterval(checkForLiveContent, 1e3);
863
892
  return () => {
864
893
  if (observerRef.current) {
865
894
  observerRef.current.disconnect();
866
895
  }
867
- clearInterval(intervalId);
868
896
  };
869
897
  }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
870
898
  return {
@@ -880,6 +908,51 @@ var useLiveIndicator = (containerRef, options = {}) => {
880
908
  };
881
909
  };
882
910
 
911
+ // src/hooks/useKeyboardControls.ts
912
+ var import_react10 = require("react");
913
+ var useKeyboardControls = (videoRef, options = {}) => {
914
+ const { skipBack, skipForward, enabled = true } = options;
915
+ const isDesktop = (0, import_react10.useCallback)(() => {
916
+ return window.innerWidth > 767 && !/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
917
+ }, []);
918
+ const handleKeydown = (0, import_react10.useCallback)((event) => {
919
+ if (!enabled || !isDesktop() || !videoRef.current) return;
920
+ const activeElement = document.activeElement;
921
+ if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)) {
922
+ return;
923
+ }
924
+ switch (event.key) {
925
+ case "ArrowLeft":
926
+ event.preventDefault();
927
+ skipBack?.();
928
+ break;
929
+ case "ArrowRight":
930
+ event.preventDefault();
931
+ skipForward?.();
932
+ break;
933
+ case " ":
934
+ case "Space":
935
+ event.preventDefault();
936
+ if (videoRef.current.paused) {
937
+ videoRef.current.play();
938
+ } else {
939
+ videoRef.current.pause();
940
+ }
941
+ break;
942
+ }
943
+ }, [enabled, videoRef, skipBack, skipForward, isDesktop]);
944
+ (0, import_react10.useEffect)(() => {
945
+ if (!enabled || !isDesktop()) return;
946
+ document.addEventListener("keydown", handleKeydown);
947
+ return () => {
948
+ document.removeEventListener("keydown", handleKeydown);
949
+ };
950
+ }, [handleKeydown, enabled, isDesktop]);
951
+ return {
952
+ isDesktop: isDesktop()
953
+ };
954
+ };
955
+
883
956
  // src/components/Loading.tsx
884
957
  var import_tailwind_merge = require("tailwind-merge");
885
958
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -996,7 +1069,7 @@ styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n
996
1069
  // src/Player.tsx
997
1070
  var import_tailwind_merge2 = require("tailwind-merge");
998
1071
  var import_jsx_runtime5 = require("react/jsx-runtime");
999
- var Player = (0, import_react10.forwardRef)(
1072
+ var Player = (0, import_react11.forwardRef)(
1000
1073
  ({
1001
1074
  src,
1002
1075
  autoPlay = false,
@@ -1016,12 +1089,12 @@ var Player = (0, import_react10.forwardRef)(
1016
1089
  seekbarConfig,
1017
1090
  events,
1018
1091
  containerClassName,
1019
- ...props
1092
+ ...videoProps
1020
1093
  }, ref) => {
1021
- const videoRef = (0, import_react10.useRef)(null);
1022
- const containerRef = (0, import_react10.useRef)(null);
1023
- const adContainerRef = (0, import_react10.useRef)(null);
1024
- (0, import_react10.useImperativeHandle)(ref, () => videoRef.current, []);
1094
+ const videoRef = (0, import_react11.useRef)(null);
1095
+ const containerRef = (0, import_react11.useRef)(null);
1096
+ const adContainerRef = (0, import_react11.useRef)(null);
1097
+ (0, import_react11.useImperativeHandle)(ref, () => videoRef.current, []);
1025
1098
  const { playerRef, initializePlayer, destroyPlayer } = useShakePlayer({
1026
1099
  src,
1027
1100
  shakaConfig,
@@ -1041,6 +1114,11 @@ var Player = (0, import_react10.forwardRef)(
1041
1114
  skipDuration,
1042
1115
  shouldShowSkipControls
1043
1116
  } = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
1117
+ useKeyboardControls(videoRef, {
1118
+ skipBack,
1119
+ skipForward,
1120
+ enabled: true
1121
+ });
1044
1122
  const {
1045
1123
  initializeMux,
1046
1124
  updateMuxData,
@@ -1116,7 +1194,7 @@ var Player = (0, import_react10.forwardRef)(
1116
1194
  console.warn("Chromecast initialization failed:", error);
1117
1195
  }
1118
1196
  };
1119
- (0, import_react10.useEffect)(() => {
1197
+ (0, import_react11.useEffect)(() => {
1120
1198
  const video = videoRef.current;
1121
1199
  if (!video) return;
1122
1200
  const initialize = async () => {
@@ -1141,22 +1219,8 @@ var Player = (0, import_react10.forwardRef)(
1141
1219
  destroyMux();
1142
1220
  destroyPlayer();
1143
1221
  };
1144
- }, [
1145
- src,
1146
- initializePlayer,
1147
- setupEventListeners,
1148
- setupQualityTracking,
1149
- configureQuality,
1150
- initializeUI,
1151
- initializeMux,
1152
- cleanupEventListeners,
1153
- destroyUI,
1154
- destroyMux,
1155
- destroyPlayer,
1156
- handleMuxError,
1157
- playerRef
1158
- ]);
1159
- (0, import_react10.useEffect)(() => {
1222
+ }, [src]);
1223
+ (0, import_react11.useEffect)(() => {
1160
1224
  const video = videoRef.current;
1161
1225
  if (!video) return;
1162
1226
  video.autoplay = autoPlay;
@@ -1165,7 +1229,14 @@ var Player = (0, import_react10.forwardRef)(
1165
1229
  video.controls = false;
1166
1230
  if (poster) video.poster = poster;
1167
1231
  }, [autoPlay, loop, muted, poster]);
1168
- (0, import_react10.useImperativeHandle)(ref, () => ({
1232
+ (0, import_react11.useEffect)(() => {
1233
+ const video = videoRef.current;
1234
+ if (!video) return;
1235
+ video.controls = false;
1236
+ video.setAttribute("controls", "false");
1237
+ video.removeAttribute("controls");
1238
+ }, []);
1239
+ (0, import_react11.useImperativeHandle)(ref, () => ({
1169
1240
  ...videoRef.current,
1170
1241
  // Custom methods for quality control
1171
1242
  getAvailableQualities,
@@ -1186,6 +1257,8 @@ var Player = (0, import_react10.forwardRef)(
1186
1257
  } : { width, height };
1187
1258
  const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
1188
1259
  const videoStyle = isResponsive ? {} : { width, height };
1260
+ const filteredVideoProps = { ...videoProps };
1261
+ delete filteredVideoProps.controls;
1189
1262
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1190
1263
  "div",
1191
1264
  {
@@ -1204,7 +1277,7 @@ var Player = (0, import_react10.forwardRef)(
1204
1277
  height: isResponsive ? void 0 : height,
1205
1278
  style: videoStyle,
1206
1279
  controls: false,
1207
- ...props
1280
+ ...filteredVideoProps
1208
1281
  }
1209
1282
  ),
1210
1283
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LiveBadge, { isVisible: isLiveBadgeVisible }),
@@ -1223,7 +1296,7 @@ var Player = (0, import_react10.forwardRef)(
1223
1296
  Player.displayName = "Player";
1224
1297
 
1225
1298
  // src/Video.tsx
1226
- var import_react12 = require("react");
1299
+ var import_react13 = require("react");
1227
1300
  var import_tailwind_merge3 = require("tailwind-merge");
1228
1301
  var import_react_query = require("@tanstack/react-query");
1229
1302
 
@@ -1364,7 +1437,7 @@ var getErrorType = (error, video) => {
1364
1437
  };
1365
1438
 
1366
1439
  // src/messages/useMessages.tsx
1367
- var import_react11 = require("react");
1440
+ var import_react12 = require("react");
1368
1441
 
1369
1442
  // src/messages/en.json
1370
1443
  var en_default = {
@@ -1666,9 +1739,9 @@ var getBrowserLanguage = () => {
1666
1739
  return availableLanguages[language] ? language : "en";
1667
1740
  };
1668
1741
  var useMessages = (locale) => {
1669
- const [language, setLanguage] = (0, import_react11.useState)("en");
1670
- const [translations, setTranslations] = (0, import_react11.useState)(availableLanguages.en);
1671
- (0, import_react11.useEffect)(() => {
1742
+ const [language, setLanguage] = (0, import_react12.useState)("en");
1743
+ const [translations, setTranslations] = (0, import_react12.useState)(availableLanguages.en);
1744
+ (0, import_react12.useEffect)(() => {
1672
1745
  const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
1673
1746
  ;
1674
1747
  setLanguage(lang);
@@ -1730,7 +1803,7 @@ var Video = ({
1730
1803
  const { t } = useMessages_default(locale);
1731
1804
  const activePlaylist = findHLSPlaylist(video);
1732
1805
  const hlsUrl = activePlaylist?.url;
1733
- (0, import_react12.useEffect)(() => {
1806
+ (0, import_react13.useEffect)(() => {
1734
1807
  if (events?.onVideoData && video) {
1735
1808
  events.onVideoData(video);
1736
1809
  }
@@ -1781,7 +1854,7 @@ var Video = ({
1781
1854
  };
1782
1855
 
1783
1856
  // src/Event.tsx
1784
- var import_react13 = require("react");
1857
+ var import_react14 = require("react");
1785
1858
  var import_tailwind_merge4 = require("tailwind-merge");
1786
1859
  var import_react_query2 = require("@tanstack/react-query");
1787
1860
  var import_jsx_runtime7 = require("react/jsx-runtime");
@@ -1814,8 +1887,8 @@ var Event = ({
1814
1887
  retry: queryOptions.retry ?? 3,
1815
1888
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1816
1889
  });
1817
- const [activePlaylist, setActivePlaylist] = (0, import_react13.useState)();
1818
- const [activeVideoId, setActiveVideoId] = (0, import_react13.useState)();
1890
+ const [activePlaylist, setActivePlaylist] = (0, import_react14.useState)();
1891
+ const [activeVideoId, setActiveVideoId] = (0, import_react14.useState)();
1819
1892
  const videoIds = eventData?.videoIds ?? [];
1820
1893
  const {
1821
1894
  data: videosData,
@@ -1831,8 +1904,8 @@ var Event = ({
1831
1904
  retry: queryOptions.retry ?? 3,
1832
1905
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1833
1906
  });
1834
- const [loadingApisState, setLoadingApisState] = (0, import_react13.useState)(true);
1835
- (0, import_react13.useEffect)(() => {
1907
+ const [loadingApisState, setLoadingApisState] = (0, import_react14.useState)(true);
1908
+ (0, import_react14.useEffect)(() => {
1836
1909
  if (videosData !== void 0) {
1837
1910
  setLoadingApisState(false);
1838
1911
  const videosWithPlaylists = videosData.filter(
@@ -1864,12 +1937,12 @@ var Event = ({
1864
1937
  }
1865
1938
  }, [videosData, eventData]);
1866
1939
  const { t } = useMessages_default(locale);
1867
- (0, import_react13.useEffect)(() => {
1940
+ (0, import_react14.useEffect)(() => {
1868
1941
  if (events?.onEventData && eventData) {
1869
1942
  events.onEventData(eventData);
1870
1943
  }
1871
1944
  }, [eventData, events]);
1872
- (0, import_react13.useEffect)(() => {
1945
+ (0, import_react14.useEffect)(() => {
1873
1946
  if (events?.onVideoData && activeVideoId && videosData) {
1874
1947
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
1875
1948
  if (activeVideo) {
@@ -1877,10 +1950,10 @@ var Event = ({
1877
1950
  }
1878
1951
  }
1879
1952
  }, [activeVideoId, videosData, events]);
1880
- const [error, setError] = (0, import_react13.useState)(null);
1881
- const [loadingPlaylist, setLoadingPlaylist] = (0, import_react13.useState)(true);
1953
+ const [error, setError] = (0, import_react14.useState)(null);
1954
+ const [loadingPlaylist, setLoadingPlaylist] = (0, import_react14.useState)(true);
1882
1955
  const videosDataError = videosData?.some((video) => !!video.error);
1883
- (0, import_react13.useEffect)(() => {
1956
+ (0, import_react14.useEffect)(() => {
1884
1957
  if (eventError || videosError || videosDataError) {
1885
1958
  const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
1886
1959
  setError(errorObj);
@@ -1891,7 +1964,7 @@ var Event = ({
1891
1964
  setError(null);
1892
1965
  }
1893
1966
  }, [eventError, videosError, videosDataError, videosData, events]);
1894
- (0, import_react13.useEffect)(() => {
1967
+ (0, import_react14.useEffect)(() => {
1895
1968
  const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
1896
1969
  const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
1897
1970
  if (eventLoadedWithNoVideos || allApisLoadedWithPotentialVideos) {
@@ -1962,12 +2035,12 @@ function PreEvent({
1962
2035
  }) {
1963
2036
  const date = new Date(event.startTime);
1964
2037
  const now = /* @__PURE__ */ new Date();
1965
- const [remainingTime, setRemainingTime] = (0, import_react13.useState)(
2038
+ const [remainingTime, setRemainingTime] = (0, import_react14.useState)(
1966
2039
  date.getTime() - now.getTime()
1967
2040
  );
1968
2041
  const shouldBeStarted = remainingTime < 0;
1969
2042
  const { t } = useMessages_default(locale);
1970
- (0, import_react13.useEffect)(() => {
2043
+ (0, import_react14.useEffect)(() => {
1971
2044
  const interval = setInterval(() => {
1972
2045
  if (remainingTime < 0) {
1973
2046
  clearInterval(interval);
@@ -1977,7 +2050,7 @@ function PreEvent({
1977
2050
  }, 1e3);
1978
2051
  return () => clearInterval(interval);
1979
2052
  }, [date, remainingTime]);
1980
- const renderCountdown = (0, import_react13.useCallback)(() => {
2053
+ const renderCountdown = (0, import_react14.useCallback)(() => {
1981
2054
  if (shouldBeStarted) {
1982
2055
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
1983
2056
  }
@@ -2107,7 +2180,7 @@ var TitleAndDescription = ({
2107
2180
  };
2108
2181
 
2109
2182
  // src/CreativeWork.tsx
2110
- var import_react14 = require("react");
2183
+ var import_react15 = require("react");
2111
2184
  var import_tailwind_merge5 = require("tailwind-merge");
2112
2185
  var import_react_query3 = require("@tanstack/react-query");
2113
2186
  var import_jsx_runtime8 = require("react/jsx-runtime");
@@ -2140,9 +2213,9 @@ var CreativeWork = ({
2140
2213
  retry: queryOptions.retry ?? 3,
2141
2214
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2142
2215
  });
2143
- const [activePlaylist, setActivePlaylist] = (0, import_react14.useState)();
2144
- const [activeVideoId, setActiveVideoId] = (0, import_react14.useState)();
2145
- const [showCountDown, setShowCountDown] = (0, import_react14.useState)(false);
2216
+ const [activePlaylist, setActivePlaylist] = (0, import_react15.useState)();
2217
+ const [activeVideoId, setActiveVideoId] = (0, import_react15.useState)();
2218
+ const [showCountDown, setShowCountDown] = (0, import_react15.useState)(false);
2146
2219
  const videoIds = creativeWorkData?.videoIds ?? [];
2147
2220
  const {
2148
2221
  data: videosData,
@@ -2158,8 +2231,8 @@ var CreativeWork = ({
2158
2231
  retry: queryOptions.retry ?? 3,
2159
2232
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2160
2233
  });
2161
- const [loadingApisState, setLoadingApisState] = (0, import_react14.useState)(true);
2162
- (0, import_react14.useEffect)(() => {
2234
+ const [loadingApisState, setLoadingApisState] = (0, import_react15.useState)(true);
2235
+ (0, import_react15.useEffect)(() => {
2163
2236
  if (videosData !== void 0) {
2164
2237
  setLoadingApisState(false);
2165
2238
  const videosWithPlaylists = videosData.filter(
@@ -2191,7 +2264,7 @@ var CreativeWork = ({
2191
2264
  }
2192
2265
  }, [videosData, creativeWorkData]);
2193
2266
  const { t } = useMessages_default(locale);
2194
- (0, import_react14.useEffect)(() => {
2267
+ (0, import_react15.useEffect)(() => {
2195
2268
  if (events?.onCreativeWorkData && creativeWorkData) {
2196
2269
  events.onCreativeWorkData(creativeWorkData);
2197
2270
  }
@@ -2199,7 +2272,7 @@ var CreativeWork = ({
2199
2272
  setShowCountDown(true);
2200
2273
  }
2201
2274
  }, [creativeWorkData, events]);
2202
- (0, import_react14.useEffect)(() => {
2275
+ (0, import_react15.useEffect)(() => {
2203
2276
  if (events?.onVideoData && activeVideoId && videosData) {
2204
2277
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
2205
2278
  if (activeVideo) {
@@ -2207,9 +2280,9 @@ var CreativeWork = ({
2207
2280
  }
2208
2281
  }
2209
2282
  }, [activeVideoId, videosData, events]);
2210
- const [error, setError] = (0, import_react14.useState)(null);
2283
+ const [error, setError] = (0, import_react15.useState)(null);
2211
2284
  const videosDataError = videosData?.some((video) => !!video.error);
2212
- (0, import_react14.useEffect)(() => {
2285
+ (0, import_react15.useEffect)(() => {
2213
2286
  if (creativeWorkError || videosError || videosDataError) {
2214
2287
  const errorObj = creativeWorkError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
2215
2288
  setError(errorObj);
@@ -2231,8 +2304,8 @@ var CreativeWork = ({
2231
2304
  }
2232
2305
  ) }) });
2233
2306
  }
2234
- const [loadingPlaylist, setLoadingPlaylist] = (0, import_react14.useState)(true);
2235
- (0, import_react14.useEffect)(() => {
2307
+ const [loadingPlaylist, setLoadingPlaylist] = (0, import_react15.useState)(true);
2308
+ (0, import_react15.useEffect)(() => {
2236
2309
  const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
2237
2310
  const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
2238
2311
  const isEventsFinished = !videosIsLoading && videosData && videosData.length > 0 && videosData.every((video) => video.playlists && video.playlists.length === 0);
@@ -2308,12 +2381,12 @@ function PreCreativeWork({
2308
2381
  }) {
2309
2382
  const date = new Date(creativeWork.releaseTime);
2310
2383
  const now = /* @__PURE__ */ new Date();
2311
- const [remainingTime, setRemainingTime] = (0, import_react14.useState)(
2384
+ const [remainingTime, setRemainingTime] = (0, import_react15.useState)(
2312
2385
  date.getTime() - now.getTime()
2313
2386
  );
2314
2387
  const shouldBeStarted = remainingTime < 0;
2315
2388
  const { t } = useMessages_default(locale);
2316
- (0, import_react14.useEffect)(() => {
2389
+ (0, import_react15.useEffect)(() => {
2317
2390
  const interval = setInterval(() => {
2318
2391
  if (remainingTime < 0) {
2319
2392
  clearInterval(interval);