@mottosports/motto-video-player 1.0.1-rc.15 → 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 () => {
@@ -1142,7 +1220,7 @@ var Player = (0, import_react10.forwardRef)(
1142
1220
  destroyPlayer();
1143
1221
  };
1144
1222
  }, [src]);
1145
- (0, import_react10.useEffect)(() => {
1223
+ (0, import_react11.useEffect)(() => {
1146
1224
  const video = videoRef.current;
1147
1225
  if (!video) return;
1148
1226
  video.autoplay = autoPlay;
@@ -1151,7 +1229,14 @@ var Player = (0, import_react10.forwardRef)(
1151
1229
  video.controls = false;
1152
1230
  if (poster) video.poster = poster;
1153
1231
  }, [autoPlay, loop, muted, poster]);
1154
- (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, () => ({
1155
1240
  ...videoRef.current,
1156
1241
  // Custom methods for quality control
1157
1242
  getAvailableQualities,
@@ -1172,6 +1257,8 @@ var Player = (0, import_react10.forwardRef)(
1172
1257
  } : { width, height };
1173
1258
  const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
1174
1259
  const videoStyle = isResponsive ? {} : { width, height };
1260
+ const filteredVideoProps = { ...videoProps };
1261
+ delete filteredVideoProps.controls;
1175
1262
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1176
1263
  "div",
1177
1264
  {
@@ -1190,7 +1277,7 @@ var Player = (0, import_react10.forwardRef)(
1190
1277
  height: isResponsive ? void 0 : height,
1191
1278
  style: videoStyle,
1192
1279
  controls: false,
1193
- ...props
1280
+ ...filteredVideoProps
1194
1281
  }
1195
1282
  ),
1196
1283
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LiveBadge, { isVisible: isLiveBadgeVisible }),
@@ -1209,7 +1296,7 @@ var Player = (0, import_react10.forwardRef)(
1209
1296
  Player.displayName = "Player";
1210
1297
 
1211
1298
  // src/Video.tsx
1212
- var import_react12 = require("react");
1299
+ var import_react13 = require("react");
1213
1300
  var import_tailwind_merge3 = require("tailwind-merge");
1214
1301
  var import_react_query = require("@tanstack/react-query");
1215
1302
 
@@ -1350,7 +1437,7 @@ var getErrorType = (error, video) => {
1350
1437
  };
1351
1438
 
1352
1439
  // src/messages/useMessages.tsx
1353
- var import_react11 = require("react");
1440
+ var import_react12 = require("react");
1354
1441
 
1355
1442
  // src/messages/en.json
1356
1443
  var en_default = {
@@ -1652,9 +1739,9 @@ var getBrowserLanguage = () => {
1652
1739
  return availableLanguages[language] ? language : "en";
1653
1740
  };
1654
1741
  var useMessages = (locale) => {
1655
- const [language, setLanguage] = (0, import_react11.useState)("en");
1656
- const [translations, setTranslations] = (0, import_react11.useState)(availableLanguages.en);
1657
- (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)(() => {
1658
1745
  const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
1659
1746
  ;
1660
1747
  setLanguage(lang);
@@ -1716,7 +1803,7 @@ var Video = ({
1716
1803
  const { t } = useMessages_default(locale);
1717
1804
  const activePlaylist = findHLSPlaylist(video);
1718
1805
  const hlsUrl = activePlaylist?.url;
1719
- (0, import_react12.useEffect)(() => {
1806
+ (0, import_react13.useEffect)(() => {
1720
1807
  if (events?.onVideoData && video) {
1721
1808
  events.onVideoData(video);
1722
1809
  }
@@ -1767,7 +1854,7 @@ var Video = ({
1767
1854
  };
1768
1855
 
1769
1856
  // src/Event.tsx
1770
- var import_react13 = require("react");
1857
+ var import_react14 = require("react");
1771
1858
  var import_tailwind_merge4 = require("tailwind-merge");
1772
1859
  var import_react_query2 = require("@tanstack/react-query");
1773
1860
  var import_jsx_runtime7 = require("react/jsx-runtime");
@@ -1800,8 +1887,8 @@ var Event = ({
1800
1887
  retry: queryOptions.retry ?? 3,
1801
1888
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1802
1889
  });
1803
- const [activePlaylist, setActivePlaylist] = (0, import_react13.useState)();
1804
- const [activeVideoId, setActiveVideoId] = (0, import_react13.useState)();
1890
+ const [activePlaylist, setActivePlaylist] = (0, import_react14.useState)();
1891
+ const [activeVideoId, setActiveVideoId] = (0, import_react14.useState)();
1805
1892
  const videoIds = eventData?.videoIds ?? [];
1806
1893
  const {
1807
1894
  data: videosData,
@@ -1817,8 +1904,8 @@ var Event = ({
1817
1904
  retry: queryOptions.retry ?? 3,
1818
1905
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1819
1906
  });
1820
- const [loadingApisState, setLoadingApisState] = (0, import_react13.useState)(true);
1821
- (0, import_react13.useEffect)(() => {
1907
+ const [loadingApisState, setLoadingApisState] = (0, import_react14.useState)(true);
1908
+ (0, import_react14.useEffect)(() => {
1822
1909
  if (videosData !== void 0) {
1823
1910
  setLoadingApisState(false);
1824
1911
  const videosWithPlaylists = videosData.filter(
@@ -1850,12 +1937,12 @@ var Event = ({
1850
1937
  }
1851
1938
  }, [videosData, eventData]);
1852
1939
  const { t } = useMessages_default(locale);
1853
- (0, import_react13.useEffect)(() => {
1940
+ (0, import_react14.useEffect)(() => {
1854
1941
  if (events?.onEventData && eventData) {
1855
1942
  events.onEventData(eventData);
1856
1943
  }
1857
1944
  }, [eventData, events]);
1858
- (0, import_react13.useEffect)(() => {
1945
+ (0, import_react14.useEffect)(() => {
1859
1946
  if (events?.onVideoData && activeVideoId && videosData) {
1860
1947
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
1861
1948
  if (activeVideo) {
@@ -1863,10 +1950,10 @@ var Event = ({
1863
1950
  }
1864
1951
  }
1865
1952
  }, [activeVideoId, videosData, events]);
1866
- const [error, setError] = (0, import_react13.useState)(null);
1867
- 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);
1868
1955
  const videosDataError = videosData?.some((video) => !!video.error);
1869
- (0, import_react13.useEffect)(() => {
1956
+ (0, import_react14.useEffect)(() => {
1870
1957
  if (eventError || videosError || videosDataError) {
1871
1958
  const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
1872
1959
  setError(errorObj);
@@ -1877,7 +1964,7 @@ var Event = ({
1877
1964
  setError(null);
1878
1965
  }
1879
1966
  }, [eventError, videosError, videosDataError, videosData, events]);
1880
- (0, import_react13.useEffect)(() => {
1967
+ (0, import_react14.useEffect)(() => {
1881
1968
  const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
1882
1969
  const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
1883
1970
  if (eventLoadedWithNoVideos || allApisLoadedWithPotentialVideos) {
@@ -1948,12 +2035,12 @@ function PreEvent({
1948
2035
  }) {
1949
2036
  const date = new Date(event.startTime);
1950
2037
  const now = /* @__PURE__ */ new Date();
1951
- const [remainingTime, setRemainingTime] = (0, import_react13.useState)(
2038
+ const [remainingTime, setRemainingTime] = (0, import_react14.useState)(
1952
2039
  date.getTime() - now.getTime()
1953
2040
  );
1954
2041
  const shouldBeStarted = remainingTime < 0;
1955
2042
  const { t } = useMessages_default(locale);
1956
- (0, import_react13.useEffect)(() => {
2043
+ (0, import_react14.useEffect)(() => {
1957
2044
  const interval = setInterval(() => {
1958
2045
  if (remainingTime < 0) {
1959
2046
  clearInterval(interval);
@@ -1963,7 +2050,7 @@ function PreEvent({
1963
2050
  }, 1e3);
1964
2051
  return () => clearInterval(interval);
1965
2052
  }, [date, remainingTime]);
1966
- const renderCountdown = (0, import_react13.useCallback)(() => {
2053
+ const renderCountdown = (0, import_react14.useCallback)(() => {
1967
2054
  if (shouldBeStarted) {
1968
2055
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
1969
2056
  }
@@ -2093,7 +2180,7 @@ var TitleAndDescription = ({
2093
2180
  };
2094
2181
 
2095
2182
  // src/CreativeWork.tsx
2096
- var import_react14 = require("react");
2183
+ var import_react15 = require("react");
2097
2184
  var import_tailwind_merge5 = require("tailwind-merge");
2098
2185
  var import_react_query3 = require("@tanstack/react-query");
2099
2186
  var import_jsx_runtime8 = require("react/jsx-runtime");
@@ -2126,9 +2213,9 @@ var CreativeWork = ({
2126
2213
  retry: queryOptions.retry ?? 3,
2127
2214
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2128
2215
  });
2129
- const [activePlaylist, setActivePlaylist] = (0, import_react14.useState)();
2130
- const [activeVideoId, setActiveVideoId] = (0, import_react14.useState)();
2131
- 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);
2132
2219
  const videoIds = creativeWorkData?.videoIds ?? [];
2133
2220
  const {
2134
2221
  data: videosData,
@@ -2144,8 +2231,8 @@ var CreativeWork = ({
2144
2231
  retry: queryOptions.retry ?? 3,
2145
2232
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2146
2233
  });
2147
- const [loadingApisState, setLoadingApisState] = (0, import_react14.useState)(true);
2148
- (0, import_react14.useEffect)(() => {
2234
+ const [loadingApisState, setLoadingApisState] = (0, import_react15.useState)(true);
2235
+ (0, import_react15.useEffect)(() => {
2149
2236
  if (videosData !== void 0) {
2150
2237
  setLoadingApisState(false);
2151
2238
  const videosWithPlaylists = videosData.filter(
@@ -2177,7 +2264,7 @@ var CreativeWork = ({
2177
2264
  }
2178
2265
  }, [videosData, creativeWorkData]);
2179
2266
  const { t } = useMessages_default(locale);
2180
- (0, import_react14.useEffect)(() => {
2267
+ (0, import_react15.useEffect)(() => {
2181
2268
  if (events?.onCreativeWorkData && creativeWorkData) {
2182
2269
  events.onCreativeWorkData(creativeWorkData);
2183
2270
  }
@@ -2185,7 +2272,7 @@ var CreativeWork = ({
2185
2272
  setShowCountDown(true);
2186
2273
  }
2187
2274
  }, [creativeWorkData, events]);
2188
- (0, import_react14.useEffect)(() => {
2275
+ (0, import_react15.useEffect)(() => {
2189
2276
  if (events?.onVideoData && activeVideoId && videosData) {
2190
2277
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
2191
2278
  if (activeVideo) {
@@ -2193,9 +2280,9 @@ var CreativeWork = ({
2193
2280
  }
2194
2281
  }
2195
2282
  }, [activeVideoId, videosData, events]);
2196
- const [error, setError] = (0, import_react14.useState)(null);
2283
+ const [error, setError] = (0, import_react15.useState)(null);
2197
2284
  const videosDataError = videosData?.some((video) => !!video.error);
2198
- (0, import_react14.useEffect)(() => {
2285
+ (0, import_react15.useEffect)(() => {
2199
2286
  if (creativeWorkError || videosError || videosDataError) {
2200
2287
  const errorObj = creativeWorkError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
2201
2288
  setError(errorObj);
@@ -2217,8 +2304,8 @@ var CreativeWork = ({
2217
2304
  }
2218
2305
  ) }) });
2219
2306
  }
2220
- const [loadingPlaylist, setLoadingPlaylist] = (0, import_react14.useState)(true);
2221
- (0, import_react14.useEffect)(() => {
2307
+ const [loadingPlaylist, setLoadingPlaylist] = (0, import_react15.useState)(true);
2308
+ (0, import_react15.useEffect)(() => {
2222
2309
  const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
2223
2310
  const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
2224
2311
  const isEventsFinished = !videosIsLoading && videosData && videosData.length > 0 && videosData.every((video) => video.playlists && video.playlists.length === 0);
@@ -2294,12 +2381,12 @@ function PreCreativeWork({
2294
2381
  }) {
2295
2382
  const date = new Date(creativeWork.releaseTime);
2296
2383
  const now = /* @__PURE__ */ new Date();
2297
- const [remainingTime, setRemainingTime] = (0, import_react14.useState)(
2384
+ const [remainingTime, setRemainingTime] = (0, import_react15.useState)(
2298
2385
  date.getTime() - now.getTime()
2299
2386
  );
2300
2387
  const shouldBeStarted = remainingTime < 0;
2301
2388
  const { t } = useMessages_default(locale);
2302
- (0, import_react14.useEffect)(() => {
2389
+ (0, import_react15.useEffect)(() => {
2303
2390
  const interval = setInterval(() => {
2304
2391
  if (remainingTime < 0) {
2305
2392
  clearInterval(interval);