@mottosports/motto-video-player 1.0.1-rc.8 → 1.0.1-rc.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,5 +1,8 @@
1
1
  "use client";
2
2
 
3
+ // src/index.ts
4
+ import "shaka-player/dist/controls.css";
5
+
3
6
  // #style-inject:#style-inject
4
7
  function styleInject(css, { insertAt } = {}) {
5
8
  if (!css || typeof document === "undefined") return;
@@ -22,73 +25,1031 @@ function styleInject(css, { insertAt } = {}) {
22
25
  }
23
26
  }
24
27
 
25
- // src/index.css
26
- 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-8 {\n height: calc(var(--spacing) * 8);\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-8 {\n width: calc(var(--spacing) * 8);\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 .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\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-border-style { syntax: "*"; inherits: false; initial-value: solid; }\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-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-border-style: solid;\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-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
28
+ // src/styles.css
29
+ styleInject(`@layer components {
30
+ video::-webkit-media-controls {
31
+ display: none !important;
32
+ }
33
+ video::-webkit-media-controls-panel {
34
+ display: none !important;
35
+ }
36
+ video::-webkit-media-controls-play-button {
37
+ display: none !important;
38
+ }
39
+ video::-webkit-media-controls-timeline {
40
+ display: none !important;
41
+ }
42
+ video::-webkit-media-controls-current-time-display {
43
+ display: none !important;
44
+ }
45
+ video::-webkit-media-controls-time-remaining-display {
46
+ display: none !important;
47
+ }
48
+ video::-webkit-media-controls-mute-button {
49
+ display: none !important;
50
+ }
51
+ video::-webkit-media-controls-volume-slider {
52
+ display: none !important;
53
+ }
54
+ video::-webkit-media-controls-fullscreen-button {
55
+ display: none !important;
56
+ }
57
+ video::-webkit-media-controls-overlay-play-button {
58
+ display: none !important;
59
+ }
60
+ video::-moz-media-controls {
61
+ display: none !important;
62
+ }
63
+ video {
64
+ outline: none !important;
65
+ }
66
+ video[controls] {
67
+ -webkit-appearance: none !important;
68
+ appearance: none !important;
69
+ }
70
+ video::-webkit-media-controls-enclosure {
71
+ display: none !important;
72
+ }
73
+ video::-webkit-media-controls-start-playback-button {
74
+ display: none !important;
75
+ }
76
+ video[controls]::-webkit-media-controls,
77
+ video[controls]::-webkit-media-controls-panel,
78
+ video[controls]::-webkit-media-controls-play-button,
79
+ video[controls]::-webkit-media-controls-timeline,
80
+ video[controls]::-webkit-media-controls-current-time-display,
81
+ video[controls]::-webkit-media-controls-time-remaining-display,
82
+ video[controls]::-webkit-media-controls-mute-button,
83
+ video[controls]::-webkit-media-controls-volume-slider,
84
+ video[controls]::-webkit-media-controls-fullscreen-button,
85
+ video[controls]::-webkit-media-controls-overlay-play-button,
86
+ video[controls]::-webkit-media-controls-enclosure,
87
+ video[controls]::-webkit-media-controls-start-playback-button {
88
+ display: none !important;
89
+ visibility: hidden !important;
90
+ opacity: 0 !important;
91
+ pointer-events: none !important;
92
+ }
93
+ video[controls]::-moz-media-controls {
94
+ display: none !important;
95
+ visibility: hidden !important;
96
+ opacity: 0 !important;
97
+ }
98
+ .motto-video-container {
99
+ @apply relative w-full;
100
+ min-height: 300px;
101
+ }
102
+ @supports (aspect-ratio: 16/9) {
103
+ .motto-video-container {
104
+ min-height: auto;
105
+ }
106
+ }
107
+ .motto-video-responsive {
108
+ @apply absolute top-0 left-0 w-full h-full;
109
+ }
110
+ .motto-skip-button {
111
+ @apply absolute top-1/2 -translate-y-1/2 bg-black/70 text-white border-0 rounded-full w-16 h-16 text-2xl cursor-pointer flex items-center justify-center transition-all duration-200 z-10 opacity-80 hover:opacity-100 hover:scale-110 active:scale-95;
112
+ }
113
+ .motto-skip-button-back {
114
+ @apply left-5;
115
+ }
116
+ .motto-skip-button-forward {
117
+ @apply right-5;
118
+ }
119
+ }
120
+ .shaka-seek-bar-container {
121
+ height: 6px !important;
122
+ width: 100% !important;
123
+ margin: 8px 0 !important;
124
+ border-radius: 4px !important;
125
+ position: relative !important;
126
+ border-top: none !important;
127
+ border-bottom: none !important;
128
+ box-shadow: none !important;
129
+ }
130
+ .shaka-seek-bar {
131
+ height: 6px !important;
132
+ width: 100% !important;
133
+ -webkit-appearance: none !important;
134
+ appearance: none !important;
135
+ background: transparent !important;
136
+ cursor: pointer !important;
137
+ border: none !important;
138
+ outline: none !important;
139
+ position: absolute !important;
140
+ top: 0 !important;
141
+ left: 0 !important;
142
+ border-radius: 4px !important;
143
+ }
144
+ .shaka-seek-bar::-webkit-slider-runnable-track {
145
+ height: 6px !important;
146
+ background: transparent !important;
147
+ border-radius: 4px !important;
148
+ border: none !important;
149
+ }
150
+ .shaka-seek-bar::-moz-range-track {
151
+ height: 6px !important;
152
+ background: transparent !important;
153
+ border-radius: 4px !important;
154
+ border: none !important;
155
+ }
156
+ .shaka-seek-bar::-webkit-slider-thumb {
157
+ -webkit-appearance: none !important;
158
+ appearance: none !important;
159
+ width: 16px !important;
160
+ height: 16px !important;
161
+ border-radius: 50% !important;
162
+ background: #ffffff !important;
163
+ cursor: pointer !important;
164
+ border: 2px solid #ffffff !important;
165
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
166
+ margin-top: -4px !important;
167
+ }
168
+ .shaka-seek-bar::-moz-range-thumb {
169
+ width: 16px !important;
170
+ height: 16px !important;
171
+ border-radius: 50% !important;
172
+ background: #ffffff !important;
173
+ cursor: pointer !important;
174
+ border: 2px solid #ffffff !important;
175
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
176
+ margin-top: -4px !important;
177
+ }
178
+ .motto-skip-back-button,
179
+ .motto-skip-forward-button,
180
+ .motto-native-skip-button {
181
+ background: transparent !important;
182
+ border: none !important;
183
+ padding: 4px !important;
184
+ margin: 0px !important;
185
+ cursor: pointer !important;
186
+ color: #ffffff !important;
187
+ transition: all 0.2s ease !important;
188
+ min-width: 32px !important;
189
+ height: 32px !important;
190
+ display: flex !important;
191
+ align-items: center !important;
192
+ justify-content: center !important;
193
+ border-radius: 4px !important;
194
+ width: 25px;
195
+ }
196
+ .motto-skip-back-button:hover,
197
+ .motto-skip-forward-button:hover,
198
+ .motto-native-skip-button:hover {
199
+ opacity: 0.8 !important;
200
+ background: transparent !important;
201
+ transform: scale(1.05) !important;
202
+ }
203
+ .motto-skip-back-button:active,
204
+ .motto-skip-forward-button:active,
205
+ .motto-native-skip-button:active {
206
+ transform: scale(0.95) !important;
207
+ }
208
+ .motto-skip-back-button svg,
209
+ .motto-skip-forward-button svg,
210
+ .motto-native-skip-button svg {
211
+ width: 24px !important;
212
+ height: 24px !important;
213
+ }
214
+ .shaka-spinner-svg {
215
+ color: white !important;
216
+ fill: white !important;
217
+ }
218
+ .shaka-spinner-path {
219
+ stroke: white !important;
220
+ fill: none !important;
221
+ }
222
+ .shaka-spinner-container {
223
+ color: white !important;
224
+ }
225
+ .shaka-buffering-spinner {
226
+ color: white !important;
227
+ fill: white !important;
228
+ }
229
+ .shaka-buffering-spinner svg {
230
+ color: white !important;
231
+ fill: white !important;
232
+ }
233
+ .shaka-buffering-spinner path {
234
+ stroke: white !important;
235
+ fill: none !important;
236
+ }
237
+ [data-shaka-player-container] .shaka-spinner,
238
+ [data-shaka-player-container] .spinner {
239
+ color: white !important;
240
+ border-color: white !important;
241
+ }
242
+ .material-icons.shaka-spinner {
243
+ color: white !important;
244
+ }
245
+ .shaka-controls-container .shaka-spinner,
246
+ .shaka-video-container .shaka-spinner {
247
+ color: white !important;
248
+ fill: white !important;
249
+ }
250
+ .shaka-controls-container .shaka-spinner svg,
251
+ .shaka-video-container .shaka-spinner svg {
252
+ color: white !important;
253
+ fill: white !important;
254
+ }
255
+ .shaka-controls-container .shaka-spinner path,
256
+ .shaka-video-container .shaka-spinner path {
257
+ stroke: white !important;
258
+ }
259
+ .motto-video-loading-overlay {
260
+ position: absolute;
261
+ top: 0;
262
+ left: 0;
263
+ width: 100%;
264
+ height: 100%;
265
+ background:
266
+ linear-gradient(
267
+ 135deg,
268
+ #1a1a1a 0%,
269
+ #2d2d2d 100%);
270
+ display: flex;
271
+ flex-direction: column;
272
+ align-items: center;
273
+ justify-content: center;
274
+ z-index: 10;
275
+ transition: opacity 0.3s ease;
276
+ }
277
+ .motto-video-loading-overlay.hidden {
278
+ opacity: 0;
279
+ pointer-events: none;
280
+ }
281
+ .motto-video-loading-content {
282
+ text-align: center;
283
+ color: white;
284
+ }
285
+ .motto-video-loading-icon {
286
+ width: 64px;
287
+ height: 64px;
288
+ margin-bottom: 16px;
289
+ opacity: 0.7;
290
+ }
291
+ .motto-video-loading-text {
292
+ font-size: 16px;
293
+ font-weight: 500;
294
+ margin-bottom: 8px;
295
+ }
296
+ .motto-video-loading-subtext {
297
+ font-size: 14px;
298
+ opacity: 0.7;
299
+ }
300
+ @keyframes pulse-live {
301
+ 0% {
302
+ opacity: 1;
303
+ transform: scale(1);
304
+ }
305
+ 50% {
306
+ opacity: 0.7;
307
+ transform: scale(1.1);
308
+ }
309
+ 100% {
310
+ opacity: 1;
311
+ transform: scale(1);
312
+ }
313
+ }
314
+ .shaka-play-button {
315
+ background: rgba(255, 255, 255, 0.1) !important;
316
+ border: none !important;
317
+ color: white !important;
318
+ padding: 10px !important;
319
+ border-radius: 100% !important;
320
+ transition: all 0.2s ease !important;
321
+ display: flex !important;
322
+ align-items: center !important;
323
+ justify-content: center !important;
324
+ min-width: 55px !important;
325
+ height: 55px !important;
326
+ }
327
+ .shaka-play-button-container {
328
+ background: transparent;
329
+ transition: all 0.2s ease !important;
330
+ }
331
+ .motto-video-container:not(.no-cursor) .shaka-play-button-container {
332
+ background: rgba(0, 0, 0, 0.3);
333
+ transition: all 0.s ease !important;
334
+ }
335
+ .shaka-play-button:hover {
336
+ background: rgba(255, 255, 255, 0.2) !important;
337
+ transform: scale(1.05) !important;
338
+ }
339
+ .shaka-play-button:active {
340
+ transform: scale(0.95) !important;
341
+ }
342
+ .shaka-play-button > * {
343
+ display: none !important;
344
+ }
345
+ .shaka-play-button::after {
346
+ content: "" !important;
347
+ width: 35px !important;
348
+ height: 35px !important;
349
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
350
+ background-repeat: no-repeat !important;
351
+ background-size: contain !important;
352
+ background-position: center !important;
353
+ display: block !important;
354
+ }
355
+ .shaka-play-button[aria-label*=Play]::after {
356
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
357
+ }
358
+ .shaka-play-button[aria-label*=Pause]::after {
359
+ background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" /></svg>') !important;
360
+ }
361
+ .motto-video-container {
362
+ background: #111111;
363
+ }
364
+ .motto-video-container video {
365
+ width: 100% !important;
366
+ height: 100% !important;
367
+ margin-left: auto !important;
368
+ margin-right: auto !important;
369
+ }
370
+ html[dir=rtl] .shaka-controls-container,
371
+ html[dir=rtl] .shaka-bottom-controls,
372
+ html[dir=rtl] .shaka-controls-button-panel {
373
+ direction: ltr !important;
374
+ }
375
+ html[dir=rtl] .shaka-overflow-menu,
376
+ html[dir=rtl] .shaka-settings-menu {
377
+ direction: rtl !important;
378
+ text-align: right !important;
379
+ }
380
+ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:not(:first-child) {
381
+ margin-right: 12px !important;
382
+ margin-left: 0 !important;
383
+ }
384
+ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:first-child {
385
+ margin-right: 0 !important;
386
+ margin-left: 12px !important;
387
+ }
388
+ .shaka-hidden-fast-forward-container,
389
+ .shaka-hidden-rewind-container {
390
+ pointer-events: none !important;
391
+ display: none !important;
392
+ }
393
+ `);
27
394
 
28
395
  // src/Player.tsx
29
- import { forwardRef, useEffect as useEffect4, useRef as useRef8, useImperativeHandle } from "react";
30
- import shaka2 from "shaka-player/dist/shaka-player.ui";
396
+ import { forwardRef, useEffect as useEffect4, useRef as useRef8, useImperativeHandle, useCallback as useCallback9, useState as useState3 } from "react";
397
+ import shaka3 from "shaka-player/dist/shaka-player.ui";
398
+
399
+ // src/hooks/useShakaPlayer.ts
400
+ import { useRef, useCallback, useState } from "react";
401
+ import shaka from "shaka-player/dist/shaka-player.ui";
31
402
 
32
- // src/hooks/useShakePlayer.ts
33
- import { useRef, useCallback } from "react";
34
- import { Player as ShakaPlayer, polyfill } from "shaka-player/dist/shaka-player.ui";
35
- var useShakePlayer = ({
403
+ // src/utils/devices.ts
404
+ var isAppleDevice = () => {
405
+ if (typeof navigator === "undefined") return false;
406
+ const ua = navigator.userAgent || "";
407
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
408
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
409
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
410
+ return isIOS || isMacSafari;
411
+ };
412
+ var isPlayReadySupported = () => {
413
+ if (typeof navigator === "undefined" || typeof window === "undefined") {
414
+ return false;
415
+ }
416
+ if (!navigator.requestMediaKeySystemAccess) {
417
+ return false;
418
+ }
419
+ const userAgent = navigator.userAgent || "";
420
+ const isXbox = /Xbox/.test(userAgent);
421
+ const isEdge = /Edg/.test(userAgent);
422
+ const isIE = /Trident|MSIE/.test(userAgent);
423
+ const isWindows = /Windows/.test(userAgent);
424
+ return isXbox || (isEdge || isIE) && isWindows;
425
+ };
426
+ var supportsWidevinePersistentLicenses = () => {
427
+ return false;
428
+ if (typeof navigator === "undefined") {
429
+ return false;
430
+ }
431
+ const userAgent = navigator.userAgent || "";
432
+ const isChromeMatch = userAgent.match(/Chrome\/(\d+)/);
433
+ if (!isChromeMatch) {
434
+ return false;
435
+ }
436
+ if (/Edg|OPR|Opera/.test(userAgent)) {
437
+ return false;
438
+ }
439
+ const chromeVersion = parseInt(isChromeMatch[1], 10);
440
+ if (chromeVersion < 64) {
441
+ return false;
442
+ }
443
+ const isMacOS = /Mac OS X|Macintosh/.test(userAgent);
444
+ const isWindows = /Windows/.test(userAgent);
445
+ return isMacOS || isWindows;
446
+ };
447
+
448
+ // src/hooks/useShakaPlayer.ts
449
+ import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
450
+
451
+ // package.json
452
+ var version = "1.0.1-rc.80";
453
+
454
+ // src/utils/licenseCache.ts
455
+ var PERSISTENT_LICENSE_PREFIX = "motto_lic_";
456
+ var LICENSE_EXPIRY_MS = 2 * 60 * 60 * 1e3;
457
+ var LICENSE_MAX_RETRY_ATTEMPTS = 10;
458
+ var getAllLicenseCacheKeys = () => {
459
+ const keys = [];
460
+ for (let i = 0; i < localStorage.length; i++) {
461
+ const key = localStorage.key(i);
462
+ if (key?.startsWith(PERSISTENT_LICENSE_PREFIX)) {
463
+ keys.push(key);
464
+ }
465
+ }
466
+ return keys;
467
+ };
468
+ var getAllLicenseCacheEntries = () => {
469
+ const keys = getAllLicenseCacheKeys();
470
+ const entries = [];
471
+ for (const key of keys) {
472
+ try {
473
+ const stored = localStorage.getItem(key);
474
+ if (stored) {
475
+ const data = JSON.parse(stored);
476
+ entries.push({ key, data });
477
+ }
478
+ } catch (error) {
479
+ console.warn(`Failed to parse license cache entry for key ${key}:`, error);
480
+ localStorage.removeItem(key);
481
+ }
482
+ }
483
+ return entries;
484
+ };
485
+ var evictLRUEntry = () => {
486
+ const entries = getAllLicenseCacheEntries();
487
+ if (entries.length === 0) {
488
+ return false;
489
+ }
490
+ entries.sort((a, b) => {
491
+ const oldestA = Math.min(...a.data.map((session) => session.timestamp));
492
+ const oldestB = Math.min(...b.data.map((session) => session.timestamp));
493
+ return oldestA - oldestB;
494
+ });
495
+ const lruEntry = entries[0];
496
+ localStorage.removeItem(lruEntry.key);
497
+ console.log(`Evicted LRU license cache entry: ${lruEntry.key}`);
498
+ return true;
499
+ };
500
+ var storeWithQuotaHandling = (key, data) => {
501
+ let attempts = 0;
502
+ while (attempts < LICENSE_MAX_RETRY_ATTEMPTS) {
503
+ try {
504
+ localStorage.setItem(key, data);
505
+ return true;
506
+ } catch (error) {
507
+ if (error instanceof DOMException && (error.code === 22 || // QUOTA_EXCEEDED_ERR
508
+ error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED")) {
509
+ console.warn(`QuotaExceededError on attempt ${attempts + 1}, attempting LRU eviction...`);
510
+ if (!evictLRUEntry()) {
511
+ console.error("No more entries to evict, storage operation failed");
512
+ return false;
513
+ }
514
+ attempts++;
515
+ } else {
516
+ console.error("Failed to store license cache data:", error);
517
+ return false;
518
+ }
519
+ }
520
+ }
521
+ console.error(`Failed to store license cache data after ${LICENSE_MAX_RETRY_ATTEMPTS} eviction attempts`);
522
+ return false;
523
+ };
524
+ var managePersistentLicenseStorage = (playlistId, licenseCacheKey, newSessionMetadata) => {
525
+ try {
526
+ const storageKey = `${PERSISTENT_LICENSE_PREFIX}${playlistId}_${licenseCacheKey}`;
527
+ const stored = localStorage.getItem(storageKey);
528
+ let existingSessions = [];
529
+ if (stored) {
530
+ try {
531
+ existingSessions = JSON.parse(stored);
532
+ } catch (parseError) {
533
+ console.warn("Failed to parse existing persistent license data:", parseError);
534
+ existingSessions = [];
535
+ }
536
+ }
537
+ const now = Date.now();
538
+ let validSessions = existingSessions.filter(
539
+ (session) => now - session.timestamp < LICENSE_EXPIRY_MS
540
+ );
541
+ if (newSessionMetadata && newSessionMetadata.length > 0) {
542
+ const newSessions = newSessionMetadata.map((session) => {
543
+ const uint8Array = new Uint8Array(session.initData);
544
+ const binaryString = Array.from(uint8Array).map((byte) => String.fromCharCode(byte)).join("");
545
+ return {
546
+ sessionId: session.sessionId,
547
+ initData: btoa(binaryString),
548
+ initDataType: session.initDataType,
549
+ keySystem: session.keySystem,
550
+ timestamp: now
551
+ };
552
+ });
553
+ const newSessionIds = new Set(newSessions.map((s) => s.sessionId));
554
+ validSessions = validSessions.filter((session) => !newSessionIds.has(session.sessionId));
555
+ validSessions = [...validSessions, ...newSessions];
556
+ }
557
+ if (validSessions.length === 0) {
558
+ localStorage.removeItem(storageKey);
559
+ } else {
560
+ const dataToStore = JSON.stringify(validSessions);
561
+ const success = storeWithQuotaHandling(storageKey, dataToStore);
562
+ if (!success) {
563
+ console.error(`Failed to store license cache for ${storageKey} after quota handling`);
564
+ return validSessions;
565
+ }
566
+ }
567
+ return validSessions;
568
+ } catch (error) {
569
+ console.warn("Failed to manage persistent license storage:", error);
570
+ return [];
571
+ }
572
+ };
573
+ var storePersistentLicense = (playlistId, licenseCacheKey, sessionMetadata) => {
574
+ managePersistentLicenseStorage(playlistId, licenseCacheKey, sessionMetadata);
575
+ };
576
+ var retrievePersistentLicense = (playlistId, licenseCacheKey) => {
577
+ try {
578
+ const validSessions = managePersistentLicenseStorage(playlistId, licenseCacheKey);
579
+ return validSessions.map((session) => ({
580
+ sessionId: session.sessionId,
581
+ initData: Uint8Array.from(atob(session.initData), (c) => c.charCodeAt(0)).buffer,
582
+ initDataType: session.initDataType,
583
+ keySystem: session.keySystem
584
+ }));
585
+ } catch (error) {
586
+ console.warn("Failed to retrieve persistent license:", error);
587
+ return [];
588
+ }
589
+ };
590
+ var clearAllPersistentLicenses = () => {
591
+ try {
592
+ const keys = getAllLicenseCacheKeys();
593
+ for (const key of keys) {
594
+ localStorage.removeItem(key);
595
+ }
596
+ console.log(`Cleared ${keys.length} persistent license cache entries`);
597
+ return keys.length;
598
+ } catch (error) {
599
+ console.error("Failed to clear persistent licenses:", error);
600
+ return 0;
601
+ }
602
+ };
603
+
604
+ // src/hooks/useShakaPlayer.ts
605
+ var normalizeSource = (src) => {
606
+ if (typeof src === "string") {
607
+ return {
608
+ id: "",
609
+ url: src,
610
+ format: "auto",
611
+ drm: {}
612
+ };
613
+ }
614
+ return src;
615
+ };
616
+ var useShakaPlayer = ({
36
617
  src,
37
618
  shakaConfig,
38
619
  drmConfig,
39
620
  onError,
40
- onPlayerReady
621
+ onPlayerReady,
622
+ muxConfig,
623
+ onMuxReady,
624
+ onMuxDataUpdate,
625
+ publicKey,
626
+ mottoToken,
627
+ hasAds = false,
628
+ hasSystem73 = false,
629
+ apiToken
41
630
  }) => {
42
631
  const playerRef = useRef(null);
43
- const initializePlayer = useCallback(async (video) => {
632
+ const [isRetrying, setIsRetrying] = useState(false);
633
+ const videoElementRef = useRef(null);
634
+ const destroyInProgressRef = useRef(null);
635
+ const isDestroyingRef = useRef(false);
636
+ const initSequenceRef = useRef(0);
637
+ const activeInitIdRef = useRef(null);
638
+ const waitingForKeyTimerRef = useRef(null);
639
+ const waitingForKeyHandlerRef = useRef(null);
640
+ const playbackResumedHandlerRef = useRef(null);
641
+ const usingPersistentLicenseRef = useRef(false);
642
+ const storedPersistentThisLoadRef = useRef(false);
643
+ const drmExpirationHandlerRef = useRef(null);
644
+ const getManifestUrl = useCallback(() => {
645
+ const playlistSrc = normalizeSource(src);
646
+ let manifestUrl = playlistSrc.url;
647
+ const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
648
+ if (isDRM) {
649
+ const isPlayReady = isPlayReadySupported();
650
+ if (isAppleDevice() && playlistSrc.drm?.fairplay?.certificateUrl) {
651
+ manifestUrl = playlistSrc.drm.fairplay.playlistUrl;
652
+ } else if (isPlayReady && playlistSrc.drm?.playready?.licenseUrl) {
653
+ manifestUrl = playlistSrc.drm.playready.playlistUrl;
654
+ } else {
655
+ manifestUrl = playlistSrc.drm?.widevine?.playlistUrl || "";
656
+ }
657
+ }
658
+ return manifestUrl;
659
+ }, [src]);
660
+ const initializePlayerInternal = useCallback(async (video) => {
44
661
  try {
45
- polyfill.installAll();
46
- if (!ShakaPlayer.isBrowserSupported()) {
662
+ if (destroyInProgressRef.current) {
663
+ try {
664
+ await destroyInProgressRef.current;
665
+ } catch {
666
+ }
667
+ }
668
+ const myInitId = ++initSequenceRef.current;
669
+ activeInitIdRef.current = myInitId;
670
+ videoElementRef.current = video;
671
+ shaka.polyfill.installAll();
672
+ if (!shaka.Player.isBrowserSupported()) {
47
673
  throw new Error("Browser not supported by Shaka Player");
48
674
  }
49
- const player = new ShakaPlayer(video);
675
+ if (isDestroyingRef.current) {
676
+ return;
677
+ }
678
+ const player = new shaka.Player();
50
679
  playerRef.current = player;
51
680
  await player.attach(video);
681
+ const defaultConfig = {
682
+ manifest: {
683
+ // Override availability window to allow DVR window to grow from start
684
+ // Set to a very large value (24 hours in seconds) to effectively allow unlimited growth
685
+ availabilityWindowOverride: 86400
686
+ // 24 hours in seconds
687
+ },
688
+ streaming: {
689
+ // Allow seeking to any point within the availability window
690
+ safeSeekOffset: 5,
691
+ // 5 seconds from live edge to prevent buffering
692
+ // Increase tolerance for manifest timing inaccuracies in live streams
693
+ inaccurateManifestTolerance: 2
694
+ }
695
+ };
696
+ player.configure(defaultConfig);
52
697
  if (shakaConfig) {
53
698
  player.configure(shakaConfig);
54
699
  }
55
- if (drmConfig) {
56
- if (drmConfig.clearKeys) {
57
- player.configure({ "drm.clearKeys": drmConfig.clearKeys });
700
+ const playlistSrc = normalizeSource(src);
701
+ const manifestUrl = getManifestUrl();
702
+ let playlistId = playlistSrc.id;
703
+ const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
704
+ storedPersistentThisLoadRef.current = false;
705
+ if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
706
+ try {
707
+ await player.destroy();
708
+ } catch {
709
+ }
710
+ if (playerRef.current === player) playerRef.current = null;
711
+ return;
712
+ }
713
+ let storedSessionsMetadata = [];
714
+ if (isDRM && playlistId) {
715
+ storedSessionsMetadata = retrievePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "");
716
+ }
717
+ if (isDRM) {
718
+ const drmConfig2 = {
719
+ servers: {
720
+ "com.widevine.alpha": playlistSrc.drm?.widevine?.licenseUrl,
721
+ "com.microsoft.playready": playlistSrc.drm?.playready?.licenseUrl,
722
+ "com.apple.fps": playlistSrc.drm?.fairplay?.licenseUrl
723
+ },
724
+ keySystemsMapping: {
725
+ // Fall back or reroute to the platform's recommended PlayReady CDM if needed
726
+ "com.microsoft.playready": "com.microsoft.playready.recommendation"
727
+ },
728
+ ...playlistSrc.drm?.fairplay && {
729
+ advanced: {
730
+ "com.apple.fps": {
731
+ serverCertificateUri: playlistSrc.drm.fairplay.certificateUrl
732
+ }
733
+ }
734
+ }
735
+ };
736
+ drmConfig2.advanced = {
737
+ ...drmConfig2.advanced,
738
+ "com.widevine.alpha": {
739
+ ...drmConfig2.advanced?.["com.widevine.alpha"],
740
+ sessionType: supportsWidevinePersistentLicenses() ? "persistent-license" : "temporary"
741
+ },
742
+ "com.microsoft.playready": {
743
+ ...drmConfig2.advanced?.["com.microsoft.playready"],
744
+ sessionType: "persistent-license"
745
+ // PlayReady seems to always require persistent-license (temporary won't work, not compatible with license server response)
746
+ },
747
+ "com.apple.fps": {
748
+ ...drmConfig2.advanced?.["com.apple.fps"],
749
+ sessionType: "temporary"
750
+ // FairPlay always uses temporary sessions - Safari won't play with persistent-license
751
+ }
752
+ };
753
+ if (storedSessionsMetadata.length > 0) {
754
+ drmConfig2.persistentSessionOnlinePlayback = true;
755
+ drmConfig2.persistentSessionsMetadata = storedSessionsMetadata.map((session) => ({
756
+ sessionId: session.sessionId,
757
+ initData: new Uint8Array(session.initData),
758
+ initDataType: session.initDataType
759
+ }));
760
+ }
761
+ usingPersistentLicenseRef.current = storedSessionsMetadata.length > 0;
762
+ player.configure({ drm: drmConfig2 });
763
+ const clearWaitingForKeyTimer = () => {
764
+ if (waitingForKeyTimerRef.current !== null) {
765
+ window.clearTimeout(waitingForKeyTimerRef.current);
766
+ waitingForKeyTimerRef.current = null;
767
+ }
768
+ };
769
+ const onPlaybackResumed = () => {
770
+ clearWaitingForKeyTimer();
771
+ };
772
+ const onWaitingForKey = () => {
773
+ if (!usingPersistentLicenseRef.current) return;
774
+ if (isRetrying) return;
775
+ clearWaitingForKeyTimer();
776
+ waitingForKeyTimerRef.current = window.setTimeout(async () => {
777
+ try {
778
+ if (isRetrying) return;
779
+ console.warn("Stuck waiting for decryption key; attempting license cache reset and reload...");
780
+ const clearedCount = clearAllPersistentLicenses();
781
+ if (clearedCount > 0 && playerRef.current) {
782
+ setIsRetrying(true);
783
+ await playerRef.current.load(getManifestUrl());
784
+ console.log("Reloaded manifest after clearing cached licenses");
785
+ } else {
786
+ console.warn("No cached licenses found to clear, skipping reload");
787
+ }
788
+ } catch (e) {
789
+ console.error("Failed during recovery from waitingforkey state:", e);
790
+ onError?.(e);
791
+ } finally {
792
+ setIsRetrying(false);
793
+ clearWaitingForKeyTimer();
794
+ }
795
+ }, 3e3);
796
+ };
797
+ try {
798
+ video.addEventListener("waitingforkey", onWaitingForKey);
799
+ video.addEventListener("playing", onPlaybackResumed);
800
+ video.addEventListener("ended", onPlaybackResumed);
801
+ video.addEventListener("pause", onPlaybackResumed);
802
+ waitingForKeyHandlerRef.current = onWaitingForKey;
803
+ playbackResumedHandlerRef.current = onPlaybackResumed;
804
+ } catch (e) {
805
+ console.warn("Failed to attach waitingforkey/playback listeners:", e);
806
+ }
807
+ const netEngine = player.getNetworkingEngine();
808
+ if (netEngine) {
809
+ netEngine.registerRequestFilter((type, request) => {
810
+ switch (type) {
811
+ case shaka.net.NetworkingEngine.RequestType.LICENSE:
812
+ if (publicKey) {
813
+ request.headers["authorization"] = `Bearer ${publicKey}`;
814
+ }
815
+ if (mottoToken) {
816
+ request.headers["x-motto-token"] = mottoToken;
817
+ }
818
+ break;
819
+ case shaka.net.NetworkingEngine.RequestType.MANIFEST:
820
+ case shaka.net.NetworkingEngine.RequestType.SEGMENT:
821
+ request.allowCrossSiteCredentials = true;
822
+ break;
823
+ }
824
+ });
825
+ netEngine.registerResponseFilter((type, response) => {
826
+ if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
827
+ const ks = player.keySystem && player.keySystem();
828
+ if (ks === "com.apple.fps") {
829
+ const responseText = shaka.util.StringUtils.fromUTF8(response.data);
830
+ response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
831
+ }
832
+ }
833
+ });
834
+ }
835
+ }
836
+ if (apiToken) {
837
+ const netEngine = player.getNetworkingEngine();
838
+ if (netEngine) {
839
+ netEngine.registerRequestFilter((type, request) => {
840
+ if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST) {
841
+ request.headers["authorization"] = `Bearer ${apiToken}`;
842
+ }
843
+ });
58
844
  }
59
- if (drmConfig.servers) {
60
- player.configure({ "drm.servers": drmConfig.servers });
845
+ }
846
+ if (isDRM && playlistId) {
847
+ const onDRMSessionUpdate = () => {
848
+ try {
849
+ if (storedPersistentThisLoadRef.current) return;
850
+ const activeDrmSessions = player.getActiveSessionsMetadata?.();
851
+ if (!activeDrmSessions) return;
852
+ const persistentSessions = activeDrmSessions.filter(
853
+ (session) => session.sessionType === "persistent-license"
854
+ );
855
+ if (persistentSessions.length > 0) {
856
+ const sessionsToStore = persistentSessions.map((session) => ({
857
+ sessionId: session.sessionId,
858
+ initData: session.initData,
859
+ initDataType: session.initDataType,
860
+ keySystem: session.keySystem || "com.widevine.alpha"
861
+ }));
862
+ storePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "", sessionsToStore);
863
+ storedPersistentThisLoadRef.current = true;
864
+ }
865
+ } catch (e) {
866
+ console.warn("Failed to persist licenses on expiration update:", e);
867
+ }
868
+ };
869
+ try {
870
+ player.addEventListener("drmsessionupdate", onDRMSessionUpdate);
871
+ drmExpirationHandlerRef.current = onDRMSessionUpdate;
872
+ } catch (e) {
873
+ console.warn("Failed to attach drmsessionupdate listener:", e);
61
874
  }
62
875
  }
63
- player.addEventListener("error", (event) => {
876
+ player?.addEventListener("error", (event) => {
64
877
  const error = event.detail;
878
+ if (error?.code === 7e3) {
879
+ return;
880
+ }
881
+ if (error?.code >= 6e3 && error?.code < 7e3 && !isRetrying && videoElementRef.current) {
882
+ console.warn(`DRM error detected (code: ${error.code}), checking for cached licenses...`);
883
+ const clearedCount = clearAllPersistentLicenses();
884
+ if (clearedCount > 0) {
885
+ console.warn(`Cleared ${clearedCount} cached licenses, retrying...`);
886
+ setIsRetrying(true);
887
+ setTimeout(async () => {
888
+ try {
889
+ const video2 = videoElementRef.current;
890
+ const currentPlayer = playerRef.current;
891
+ if (video2 && currentPlayer) {
892
+ console.log("Reloading manifest after license cache clear...");
893
+ await currentPlayer.load(getManifestUrl());
894
+ console.log("Manifest reloaded successfully");
895
+ }
896
+ } catch (retryError) {
897
+ console.error("Failed to retry after license clear:", retryError);
898
+ onError?.(retryError);
899
+ } finally {
900
+ setIsRetrying(false);
901
+ }
902
+ }, 500);
903
+ return;
904
+ } else {
905
+ console.warn(`No cached licenses found to clear for error code ${error.code}, not retrying to avoid infinite loop`);
906
+ }
907
+ }
65
908
  console.error("Shaka Player Error:", error);
66
909
  onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
67
910
  });
68
- await player.load(src);
911
+ if (muxConfig) {
912
+ try {
913
+ const playerInitTime = initShakaPlayerMux.utils.now();
914
+ const muxOptions = {
915
+ debug: muxConfig.debug || false,
916
+ disableCookies: muxConfig.disableCookies || false,
917
+ respectDoNotTrack: muxConfig.respectDoNotTrack || false,
918
+ automaticErrorTracking: muxConfig.automaticErrorTracking !== false,
919
+ ...muxConfig.beaconCollectionDomain && { beaconCollectionDomain: muxConfig.beaconCollectionDomain },
920
+ ...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
921
+ data: {
922
+ env_key: muxConfig.envKey,
923
+ player_name: muxConfig?.metadata?.player_name,
924
+ player_version: version,
925
+ player_init_time: playerInitTime,
926
+ video_title: muxConfig?.metadata?.video_title ?? "",
927
+ video_id: muxConfig?.metadata?.video_id ?? "",
928
+ viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
929
+ ...muxConfig.metadata
930
+ }
931
+ };
932
+ initShakaPlayerMux(player, muxOptions, shaka);
933
+ onMuxReady?.();
934
+ } catch (error) {
935
+ console.error("Failed to initialize Mux Analytics:", error);
936
+ }
937
+ }
938
+ if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
939
+ try {
940
+ await player.destroy();
941
+ } catch {
942
+ }
943
+ if (playerRef.current === player) playerRef.current = null;
944
+ return;
945
+ }
946
+ if (!hasAds && !hasSystem73) {
947
+ console.log("\u{1F4FA} [Shaka] Auto-loading manifest:", manifestUrl);
948
+ await player.load(manifestUrl);
949
+ console.log("\u2705 [Shaka] Manifest auto-loaded successfully");
950
+ } else {
951
+ console.log("\u23ED\uFE0F [Shaka] Skipping auto-load (hasAds:", hasAds, ", hasSystem73:", hasSystem73, ")");
952
+ }
69
953
  onPlayerReady?.(player);
70
954
  return player;
71
955
  } catch (error) {
956
+ if (error?.code === 7e3) {
957
+ return;
958
+ }
72
959
  console.error("Error initializing Shaka Player:", error);
73
960
  onError?.(error);
74
961
  throw error;
75
962
  }
76
- }, [shakaConfig, drmConfig, src, onError, onPlayerReady]);
963
+ }, [shakaConfig, drmConfig, src, onError, onPlayerReady, muxConfig, onMuxReady, isRetrying, getManifestUrl, apiToken]);
964
+ const initializePlayer = useCallback(async (video) => {
965
+ return initializePlayerInternal(video);
966
+ }, [initializePlayerInternal]);
967
+ const loadManifest = useCallback(async () => {
968
+ const player = playerRef.current;
969
+ if (!player) {
970
+ console.warn("\u26A0\uFE0F [Shaka] Cannot load manifest: player not initialized");
971
+ return;
972
+ }
973
+ try {
974
+ const manifestUrl = getManifestUrl();
975
+ console.log("\u{1F4FA} [Shaka] Loading manifest:", manifestUrl);
976
+ await player.load(manifestUrl);
977
+ console.log("\u2705 [Shaka] Manifest loaded successfully");
978
+ } catch (error) {
979
+ if (error?.code === 7e3) {
980
+ return;
981
+ }
982
+ console.error("\u274C [Shaka] Error loading manifest:", error);
983
+ onError?.(error);
984
+ throw error;
985
+ }
986
+ }, [getManifestUrl, onError]);
77
987
  const destroyPlayer = useCallback(async () => {
78
- if (playerRef.current) {
988
+ const playerInstance = playerRef.current;
989
+ if (playerInstance) {
79
990
  try {
80
- await playerRef.current.destroy();
991
+ isDestroyingRef.current = true;
992
+ activeInitIdRef.current = null;
993
+ if (videoElementRef.current) {
994
+ try {
995
+ if (waitingForKeyHandlerRef.current) {
996
+ videoElementRef.current.removeEventListener("waitingforkey", waitingForKeyHandlerRef.current);
997
+ }
998
+ if (playbackResumedHandlerRef.current) {
999
+ videoElementRef.current.removeEventListener("playing", playbackResumedHandlerRef.current);
1000
+ videoElementRef.current.removeEventListener("ended", playbackResumedHandlerRef.current);
1001
+ videoElementRef.current.removeEventListener("pause", playbackResumedHandlerRef.current);
1002
+ }
1003
+ } catch (e) {
1004
+ console.warn("Error removing media event listeners:", e);
1005
+ }
1006
+ }
1007
+ if (waitingForKeyTimerRef.current !== null) {
1008
+ window.clearTimeout(waitingForKeyTimerRef.current);
1009
+ waitingForKeyTimerRef.current = null;
1010
+ }
1011
+ try {
1012
+ if (drmExpirationHandlerRef.current && playerInstance.removeEventListener) {
1013
+ playerInstance.removeEventListener("drmsessionupdate", drmExpirationHandlerRef.current);
1014
+ }
1015
+ } catch (e) {
1016
+ console.warn("Error removing DRM expiration listener:", e);
1017
+ } finally {
1018
+ drmExpirationHandlerRef.current = null;
1019
+ }
1020
+ const performDestroy = async () => {
1021
+ try {
1022
+ await playerInstance.destroy();
1023
+ } finally {
1024
+ try {
1025
+ if (videoElementRef.current) {
1026
+ videoElementRef.current.removeAttribute("src");
1027
+ videoElementRef.current.load();
1028
+ }
1029
+ } catch {
1030
+ }
1031
+ }
1032
+ };
1033
+ destroyInProgressRef.current = performDestroy();
1034
+ await destroyInProgressRef.current;
81
1035
  } catch (error) {
82
1036
  console.warn("Error destroying Shaka Player:", error);
83
1037
  } finally {
84
- playerRef.current = null;
1038
+ if (playerRef.current === playerInstance) {
1039
+ playerRef.current = null;
1040
+ }
1041
+ storedPersistentThisLoadRef.current = false;
1042
+ isDestroyingRef.current = false;
1043
+ destroyInProgressRef.current = null;
85
1044
  }
86
1045
  }
87
- }, []);
1046
+ }, [playerRef]);
88
1047
  return {
89
1048
  playerRef,
90
1049
  initializePlayer,
91
- destroyPlayer
1050
+ loadManifest,
1051
+ destroyPlayer,
1052
+ isRetrying
92
1053
  };
93
1054
  };
94
1055
 
@@ -111,11 +1072,25 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
111
1072
  if (!playerRef.current) return;
112
1073
  if (height === 0) {
113
1074
  playerRef.current.configure({
114
- abr: { enabled: true }
1075
+ abr: {
1076
+ enabled: true,
1077
+ switchInterval: 2,
1078
+ // quicker re-checks
1079
+ clearBufferSwitch: true,
1080
+ safeMarginSwitch: 10
1081
+ // leave ~10 s in front of the playhead }
1082
+ }
115
1083
  });
116
1084
  } else {
117
1085
  playerRef.current.configure({
118
- abr: { enabled: false }
1086
+ abr: {
1087
+ enabled: false,
1088
+ switchInterval: 2,
1089
+ // quicker re-checks
1090
+ clearBufferSwitch: true,
1091
+ safeMarginSwitch: 10
1092
+ // leave ~10 s in front of the playhead }
1093
+ }
119
1094
  });
120
1095
  const tracks = playerRef.current.getVariantTracks();
121
1096
  const targetTrack = tracks.find((track) => track.height === height);
@@ -194,14 +1169,14 @@ var useSkipControls = (videoRef, onSkipBack, onSkipForward) => {
194
1169
 
195
1170
  // src/hooks/useMuxAnalytics.ts
196
1171
  import { useCallback as useCallback4, useRef as useRef3 } from "react";
197
- import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
198
- import shaka from "shaka-player/dist/shaka-player.ui";
1172
+ import initShakaPlayerMux2 from "@mux/mux-data-shakaplayer";
1173
+ import shaka2 from "shaka-player/dist/shaka-player.ui";
199
1174
  var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
200
1175
  const shakaPlayerMuxRef = useRef3(null);
201
1176
  const initializeMux = useCallback4(() => {
202
1177
  if (!muxConfig || !playerRef.current) return;
203
1178
  try {
204
- const playerInitTime = initShakaPlayerMux.utils.now();
1179
+ const playerInitTime = initShakaPlayerMux2.utils.now();
205
1180
  const muxOptions = {
206
1181
  debug: muxConfig.debug || false,
207
1182
  disableCookies: muxConfig.disableCookies || false,
@@ -211,13 +1186,16 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
211
1186
  ...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
212
1187
  data: {
213
1188
  env_key: muxConfig.envKey,
214
- player_name: "Motto Video Player",
215
- player_version: "1.0.0",
1189
+ player_name: muxConfig?.metadata?.player_name,
1190
+ player_version: version,
216
1191
  player_init_time: playerInitTime,
1192
+ video_title: muxConfig?.metadata?.video_title ?? "",
1193
+ video_id: muxConfig?.metadata?.video_id ?? "",
1194
+ viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
217
1195
  ...muxConfig.metadata
218
1196
  }
219
1197
  };
220
- shakaPlayerMuxRef.current = initShakaPlayerMux(playerRef.current, muxOptions, shaka);
1198
+ shakaPlayerMuxRef.current = initShakaPlayerMux2(playerRef.current, muxOptions, shaka2);
221
1199
  onMuxReady?.();
222
1200
  } catch (error) {
223
1201
  console.error("Failed to initialize Mux Analytics:", error);
@@ -262,8 +1240,155 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
262
1240
  // src/hooks/useShakaUI.ts
263
1241
  import { useCallback as useCallback5, useRef as useRef4 } from "react";
264
1242
  import { ui as ShakaUI } from "shaka-player/dist/shaka-player.ui";
1243
+
1244
+ // src/icons/SkipBackIcon.tsx
1245
+ import { jsx, jsxs } from "react/jsx-runtime";
1246
+ var SkipBackIcon = ({ size = 24, className = "" }) => {
1247
+ return /* @__PURE__ */ jsxs(
1248
+ "svg",
1249
+ {
1250
+ width: size,
1251
+ height: size,
1252
+ strokeWidth: "2",
1253
+ viewBox: "0 0 24 24",
1254
+ fill: "none",
1255
+ xmlns: "http://www.w3.org/2000/svg",
1256
+ className,
1257
+ children: [
1258
+ /* @__PURE__ */ jsx(
1259
+ "path",
1260
+ {
1261
+ d: "M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4",
1262
+ stroke: "currentColor",
1263
+ strokeWidth: "2",
1264
+ strokeLinecap: "round",
1265
+ strokeLinejoin: "round"
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ jsx(
1269
+ "path",
1270
+ {
1271
+ d: "M9 9L9 16",
1272
+ stroke: "currentColor",
1273
+ strokeWidth: "2",
1274
+ strokeLinecap: "round",
1275
+ strokeLinejoin: "round"
1276
+ }
1277
+ ),
1278
+ /* @__PURE__ */ jsx(
1279
+ "path",
1280
+ {
1281
+ d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
1282
+ stroke: "currentColor",
1283
+ strokeWidth: "2",
1284
+ strokeLinecap: "round",
1285
+ strokeLinejoin: "round"
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsx(
1289
+ "path",
1290
+ {
1291
+ d: "M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6",
1292
+ stroke: "currentColor",
1293
+ strokeWidth: "2",
1294
+ strokeLinecap: "round",
1295
+ strokeLinejoin: "round"
1296
+ }
1297
+ )
1298
+ ]
1299
+ }
1300
+ );
1301
+ };
1302
+
1303
+ // src/icons/SkipForwardIcon.tsx
1304
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1305
+ var SkipForwardIcon = ({ size = 24, className = "" }) => {
1306
+ return /* @__PURE__ */ jsxs2(
1307
+ "svg",
1308
+ {
1309
+ width: size,
1310
+ height: size,
1311
+ strokeWidth: "2",
1312
+ viewBox: "0 0 24 24",
1313
+ fill: "none",
1314
+ xmlns: "http://www.w3.org/2000/svg",
1315
+ className,
1316
+ children: [
1317
+ /* @__PURE__ */ jsx2(
1318
+ "path",
1319
+ {
1320
+ d: "M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4",
1321
+ stroke: "currentColor",
1322
+ strokeLinecap: "round",
1323
+ strokeLinejoin: "round"
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsx2(
1327
+ "path",
1328
+ {
1329
+ d: "M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6",
1330
+ stroke: "currentColor",
1331
+ strokeLinecap: "round",
1332
+ strokeLinejoin: "round"
1333
+ }
1334
+ ),
1335
+ /* @__PURE__ */ jsx2(
1336
+ "path",
1337
+ {
1338
+ d: "M9 9L9 16",
1339
+ stroke: "currentColor",
1340
+ strokeLinecap: "round",
1341
+ strokeLinejoin: "round"
1342
+ }
1343
+ ),
1344
+ /* @__PURE__ */ jsx2(
1345
+ "path",
1346
+ {
1347
+ d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
1348
+ stroke: "currentColor",
1349
+ strokeLinecap: "round",
1350
+ strokeLinejoin: "round"
1351
+ }
1352
+ )
1353
+ ]
1354
+ }
1355
+ );
1356
+ };
1357
+
1358
+ // src/icons/BigPlayIcon.tsx
1359
+ import { jsx as jsx3 } from "react/jsx-runtime";
1360
+ var BigPlayIcon = ({ size = 40, className = "" }) => {
1361
+ return /* @__PURE__ */ jsx3(
1362
+ "svg",
1363
+ {
1364
+ width: size,
1365
+ height: size,
1366
+ viewBox: "0 0 24 24",
1367
+ fill: "currentColor",
1368
+ xmlns: "http://www.w3.org/2000/svg",
1369
+ className,
1370
+ children: /* @__PURE__ */ jsx3(
1371
+ "path",
1372
+ {
1373
+ fillRule: "evenodd",
1374
+ d: "M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z",
1375
+ clipRule: "evenodd"
1376
+ }
1377
+ )
1378
+ }
1379
+ );
1380
+ };
1381
+
1382
+ // src/utils/renderIcon.ts
1383
+ import { renderToStaticMarkup } from "react-dom/server";
1384
+ import { createElement } from "react";
1385
+ var renderIcon = (Component, props = {}) => {
1386
+ return renderToStaticMarkup(createElement(Component, props));
1387
+ };
1388
+
1389
+ // src/hooks/useShakaUI.ts
265
1390
  var SkipBackButton = class {
266
- constructor(parent, controls, onSkipBack) {
1391
+ constructor(parent, controls, onSkipBack, iconSize = 24) {
267
1392
  this.parent = parent;
268
1393
  this.controls = controls;
269
1394
  this.eventManager = { listen: (element, event, handler) => {
@@ -271,14 +1396,7 @@ var SkipBackButton = class {
271
1396
  } };
272
1397
  this.button_ = document.createElement("button");
273
1398
  this.button_.className = "shaka-button motto-native-skip-button";
274
- this.button_.innerHTML = `
275
- <svg width="24px" stroke-width="2" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
276
- <path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
277
- <path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
278
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
279
- <path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
280
- </svg>
281
- `;
1399
+ this.button_.innerHTML = renderIcon(SkipBackIcon, { size: iconSize });
282
1400
  this.button_.title = "Skip back 15 seconds";
283
1401
  this.button_.setAttribute("aria-label", "Skip back 15 seconds");
284
1402
  this.parent.appendChild(this.button_);
@@ -291,9 +1409,13 @@ var SkipBackButton = class {
291
1409
  }
292
1410
  });
293
1411
  }
1412
+ // Shaka UI will call `release` when the controls are destroyed.
1413
+ // Provide a no-op implementation to avoid TypeErrors.
1414
+ release() {
1415
+ }
294
1416
  };
295
1417
  var SkipForwardButton = class {
296
- constructor(parent, controls, onSkipForward) {
1418
+ constructor(parent, controls, onSkipForward, iconSize = 24) {
297
1419
  this.parent = parent;
298
1420
  this.controls = controls;
299
1421
  this.eventManager = { listen: (element, event, handler) => {
@@ -301,14 +1423,7 @@ var SkipForwardButton = class {
301
1423
  } };
302
1424
  this.button_ = document.createElement("button");
303
1425
  this.button_.className = "shaka-button motto-native-skip-button";
304
- this.button_.innerHTML = `
305
- <svg fill="none" height="24" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
306
- <path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
307
- <path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
308
- <path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
309
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
310
- </svg>
311
- `;
1426
+ this.button_.innerHTML = renderIcon(SkipForwardIcon, { size: iconSize });
312
1427
  this.button_.title = "Skip forward 15 seconds";
313
1428
  this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
314
1429
  this.parent.appendChild(this.button_);
@@ -321,243 +1436,65 @@ var SkipForwardButton = class {
321
1436
  }
322
1437
  });
323
1438
  }
1439
+ release() {
1440
+ }
324
1441
  };
325
1442
  var SkipBackButtonFactory = class {
326
- constructor(onSkipBack) {
1443
+ constructor(onSkipBack, iconSize) {
327
1444
  this.onSkipBack = onSkipBack;
1445
+ this.iconSize = iconSize;
328
1446
  }
329
1447
  create(rootElement, controls) {
330
- return new SkipBackButton(rootElement, controls, this.onSkipBack);
1448
+ return new SkipBackButton(rootElement, controls, this.onSkipBack, this.iconSize);
331
1449
  }
332
1450
  };
333
1451
  var SkipForwardButtonFactory = class {
334
- constructor(onSkipForward) {
335
- this.onSkipForward = onSkipForward;
336
- }
337
- create(rootElement, controls) {
338
- return new SkipForwardButton(rootElement, controls, this.onSkipForward);
339
- }
340
- };
341
- var MobilePlayButton = class {
342
- constructor(parent, controls) {
343
- this.parent = parent;
344
- this.controls = controls;
345
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
346
- if (!this.video) {
347
- console.error("MobilePlayButton: No video element found");
348
- return;
349
- }
350
- this.eventManager = { listen: (element, event, handler) => {
351
- element.addEventListener(event, handler);
352
- } };
353
- this.button_ = document.createElement("button");
354
- this.button_.className = "motto-mobile-play-button";
355
- this.updateIcon();
356
- this.parent.appendChild(this.button_);
357
- this.eventManager.listen(this.button_, "click", () => {
358
- if (this.video.paused) {
359
- this.video.play();
360
- } else {
361
- this.video.pause();
362
- }
363
- });
364
- this.eventManager.listen(this.video, "play", () => this.updateIcon());
365
- this.eventManager.listen(this.video, "pause", () => this.updateIcon());
366
- }
367
- updateIcon() {
368
- if (this.video.paused) {
369
- this.button_.innerHTML = `
370
- <svg xmlns="http://www.w3.org/2000/svg" stroke-width="2" viewBox="0 0 24 24" fill="currentColor">
371
- <path stroke-width="2" fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
372
- </svg>
373
- `;
374
- this.button_.setAttribute("aria-label", "Play");
375
- } else {
376
- this.button_.innerHTML = `
377
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
378
- <path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" />
379
- </svg>
380
- `;
381
- this.button_.setAttribute("aria-label", "Pause");
382
- }
383
- }
384
- };
385
- var MobileSkipBackButton = class {
386
- constructor(parent, controls, onSkipBack) {
387
- this.parent = parent;
388
- this.controls = controls;
389
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
390
- if (!this.video) {
391
- console.error("MobileSkipBackButton: No video element found");
392
- return;
393
- }
394
- this.eventManager = { listen: (element, event, handler) => {
395
- element.addEventListener(event, handler);
396
- } };
397
- this.button_ = document.createElement("button");
398
- this.button_.className = "motto-mobile-skip-button";
399
- this.button_.innerHTML = `
400
- <svg width="20px" stroke-width="2" height="20px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
401
- <path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
402
- <path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
403
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
404
- <path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
405
- </svg>
406
- `;
407
- this.button_.setAttribute("aria-label", "Skip back 15 seconds");
408
- this.parent.appendChild(this.button_);
409
- this.eventManager.listen(this.button_, "click", () => {
410
- const newTime = Math.max(0, this.video.currentTime - 15);
411
- this.video.currentTime = newTime;
412
- onSkipBack?.(newTime);
413
- });
414
- }
415
- };
416
- var MobileSkipForwardButton = class {
417
- constructor(parent, controls, onSkipForward) {
418
- this.parent = parent;
419
- this.controls = controls;
420
- this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
421
- if (!this.video) {
422
- console.error("MobileSkipForwardButton: No video element found");
423
- return;
424
- }
425
- this.eventManager = { listen: (element, event, handler) => {
426
- element.addEventListener(event, handler);
427
- } };
428
- this.button_ = document.createElement("button");
429
- this.button_.className = "motto-mobile-skip-button";
430
- this.button_.innerHTML = `
431
- <svg fill="none" height="20" stroke-width="2" viewBox="0 0 24 24" width="20" xmlns="http://www.w3.org/2000/svg">
432
- <path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
433
- <path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
434
- <path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
435
- <path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
436
- </svg>
437
- `;
438
- this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
439
- this.parent.appendChild(this.button_);
440
- this.eventManager.listen(this.button_, "click", () => {
441
- const newTime = Math.min(this.video.duration || 0, this.video.currentTime + 15);
442
- this.video.currentTime = newTime;
443
- onSkipForward?.(newTime);
444
- });
445
- }
446
- };
447
- var MobileControlsContainer = class {
448
- constructor(parent, controls, onSkipBack, onSkipForward) {
449
- this.parent = parent;
450
- this.controls = controls;
451
- if (!parent) {
452
- console.error("MobileControlsContainer: No parent element provided");
453
- return;
454
- }
455
- this.container_ = document.createElement("div");
456
- this.container_.className = "motto-mobile-controls-overlay";
457
- const controlsGroup = document.createElement("div");
458
- controlsGroup.className = "motto-mobile-controls-group";
459
- new MobileSkipBackButton(controlsGroup, controls, onSkipBack);
460
- new MobilePlayButton(controlsGroup, controls);
461
- new MobileSkipForwardButton(controlsGroup, controls, onSkipForward);
462
- this.container_.appendChild(controlsGroup);
463
- this.parent.appendChild(this.container_);
464
- this.setupVisibilitySync();
465
- }
466
- setupVisibilitySync() {
467
- setTimeout(() => {
468
- this.syncVisibility();
469
- this.observer = new MutationObserver((mutations) => {
470
- mutations.forEach((mutation) => {
471
- if (mutation.type === "attributes" && mutation.attributeName === "class") {
472
- this.syncVisibility();
473
- }
474
- });
475
- });
476
- this.observer.observe(this.parent, {
477
- attributes: true,
478
- attributeFilter: ["class"]
479
- });
480
- const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
481
- if (video) {
482
- video.addEventListener("play", () => {
483
- setTimeout(() => this.syncVisibility(), 50);
484
- });
485
- video.addEventListener("pause", () => {
486
- setTimeout(() => this.syncVisibility(), 50);
487
- });
488
- }
489
- }, 1e3);
490
- }
491
- syncVisibility() {
492
- const mainContainer = this.parent;
493
- const hasNoCursor = mainContainer.classList.contains("no-cursor");
494
- const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
495
- const isVideoPaused = video ? video.paused : false;
496
- const isControlsVisible = !hasNoCursor || isVideoPaused;
497
- if (this.container_) {
498
- if (isControlsVisible) {
499
- this.container_.style.opacity = "1";
500
- this.container_.style.pointerEvents = "none";
501
- } else {
502
- this.container_.style.opacity = "0";
503
- this.container_.style.pointerEvents = "none";
504
- }
505
- }
506
- }
507
- isElementVisible(element) {
508
- const style = window.getComputedStyle(element);
509
- const hasHiddenClass = element.classList.contains("shaka-hidden") || element.classList.contains("hidden") || element.classList.contains("shaka-fade-out");
510
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && !element.hidden && !hasHiddenClass;
511
- }
512
- };
513
- var MobileControlsContainerFactory = class {
514
- constructor(onSkipBack, onSkipForward) {
515
- this.onSkipBack = onSkipBack;
1452
+ constructor(onSkipForward, iconSize) {
516
1453
  this.onSkipForward = onSkipForward;
1454
+ this.iconSize = iconSize;
517
1455
  }
518
1456
  create(rootElement, controls) {
519
- return new MobileControlsContainer(rootElement, controls, this.onSkipBack, this.onSkipForward);
1457
+ return new SkipForwardButton(rootElement, controls, this.onSkipForward, this.iconSize);
520
1458
  }
521
1459
  };
522
- var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
1460
+ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale = "en") => {
523
1461
  const uiRef = useRef4(null);
524
1462
  const registeredElements = useRef4(/* @__PURE__ */ new Set());
525
1463
  const initializeUI = useCallback5(async () => {
526
1464
  if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
527
1465
  return null;
528
1466
  }
529
- const isMobile = window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
530
1467
  if (!registeredElements.current.has("skip_back_button")) {
531
- ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack));
1468
+ ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack, iconSizes?.skipButtons));
532
1469
  registeredElements.current.add("skip_back_button");
533
1470
  }
534
1471
  if (!registeredElements.current.has("skip_forward_button")) {
535
- ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward));
1472
+ ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward, iconSizes?.skipButtons));
536
1473
  registeredElements.current.add("skip_forward_button");
537
1474
  }
538
- if (isMobile) {
539
- if (!registeredElements.current.has("mobile_controls_container")) {
540
- ShakaUI.Controls.registerElement("mobile_controls_container", new MobileControlsContainerFactory(onSkipBack, onSkipForward));
541
- registeredElements.current.add("mobile_controls_container");
542
- }
543
- }
544
1475
  const ui = new ShakaUI.Overlay(playerRef.current, containerRef.current, videoRef.current);
545
1476
  uiRef.current = ui;
546
- const controlPanelElements = isMobile ? [
547
- "mute",
548
- "time_and_duration",
549
- "spacer",
550
- "fullscreen",
551
- "overflow_menu"
552
- ] : [
553
- "skip_back_button",
554
- "play_pause",
555
- "skip_forward_button",
1477
+ if (locale !== "en") {
1478
+ try {
1479
+ ui.getControls().getLocalization().changeLocale([locale]);
1480
+ console.log(`Set locale to '${locale}'`);
1481
+ } catch (error) {
1482
+ console.warn(`Failed to set locale to '${locale}', falling back to 'en':`, error);
1483
+ }
1484
+ }
1485
+ const isMobile = window.innerWidth <= 767;
1486
+ const controlPanelElements = [
1487
+ ...isMobile ? [] : ["skip_back_button"],
1488
+ ...isMobile ? [] : ["play_pause"],
1489
+ ...isMobile ? [] : ["skip_forward_button"],
556
1490
  "mute",
557
- "volume",
1491
+ ...isMobile ? [] : ["volume"],
1492
+ // Only include volume on desktop
558
1493
  "time_and_duration",
559
1494
  "spacer",
560
1495
  "fullscreen",
1496
+ "cast",
1497
+ // Always show cast button
561
1498
  "overflow_menu"
562
1499
  ];
563
1500
  const uiConfig = {
@@ -570,35 +1507,58 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
570
1507
  // Progress/played portion (white)
571
1508
  },
572
1509
  controlPanelElements,
573
- ...chromecastConfig?.receiverApplicationId && {
574
- "castReceiverAppId": chromecastConfig.receiverApplicationId,
575
- "castAndroidReceiverCompatible": false
576
- }
1510
+ addBigPlayButton: isMobile,
1511
+ // For now, Chromecast via Shaka must use the Motto receiver that runs on the legacy cast SDK (2.0), because
1512
+ // Shaka does not support the newer Cast SDK (3.0+) in its native integration.
1513
+ castReceiverAppId: "EC900D4D",
1514
+ castAndroidReceiverCompatible: true,
1515
+ // Enable Android TV compatibility
1516
+ overflowMenuButtons: [
1517
+ "quality",
1518
+ "picture_in_picture",
1519
+ "playback_rate"
1520
+ ]
577
1521
  };
578
- if (chromecastConfig?.receiverApplicationId) {
579
- uiConfig.castReceiverAppId = chromecastConfig.receiverApplicationId;
580
- uiConfig.castAndroidReceiverCompatible = false;
581
- }
582
1522
  ui.configure(uiConfig);
583
1523
  if (isMobile) {
584
- setTimeout(() => {
585
- const container = containerRef.current;
586
- const video = videoRef.current;
587
- if (container && video) {
588
- new MobileControlsContainer(container, { getVideo: () => video }, onSkipBack, onSkipForward);
1524
+ const customizeBigPlayButton = () => {
1525
+ const bigPlayButton = containerRef.current?.querySelector(".shaka-big-play-button");
1526
+ if (bigPlayButton && !bigPlayButton.hasAttribute("data-customized")) {
1527
+ const buttonSize = iconSizes?.bigPlayButton || 40;
1528
+ bigPlayButton.innerHTML = renderIcon(BigPlayIcon, { size: buttonSize });
1529
+ bigPlayButton.setAttribute("data-customized", "true");
1530
+ const buttonElement = bigPlayButton;
1531
+ buttonElement.style.display = "flex";
1532
+ buttonElement.style.alignItems = "center";
1533
+ buttonElement.style.justifyContent = "center";
589
1534
  }
590
- }, 500);
1535
+ };
1536
+ setTimeout(customizeBigPlayButton, 100);
1537
+ const observer = new MutationObserver(() => {
1538
+ customizeBigPlayButton();
1539
+ });
1540
+ if (containerRef.current) {
1541
+ observer.observe(containerRef.current, {
1542
+ childList: true,
1543
+ subtree: true,
1544
+ attributes: false
1545
+ });
1546
+ }
591
1547
  }
592
1548
  return ui;
593
- }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward]);
594
- const destroyUI = useCallback5(() => {
595
- if (uiRef.current) {
1549
+ }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale]);
1550
+ const destroyUI = useCallback5(async () => {
1551
+ const uiInstance = uiRef.current;
1552
+ if (uiInstance) {
596
1553
  try {
597
- uiRef.current.destroy();
1554
+ await uiInstance.destroy();
598
1555
  } catch (error) {
599
1556
  console.error("Error destroying UI:", error);
1557
+ } finally {
1558
+ if (uiRef.current === uiInstance) {
1559
+ uiRef.current = null;
1560
+ }
600
1561
  }
601
- uiRef.current = null;
602
1562
  }
603
1563
  }, []);
604
1564
  return {
@@ -637,128 +1597,153 @@ var useEventHandlers = (videoRef, handlers) => {
637
1597
  };
638
1598
  };
639
1599
 
640
- // src/hooks/useLiveBadge.ts
641
- import { useEffect, useState, useRef as useRef5 } from "react";
642
- var useLiveBadge = (playerRef, options = {}) => {
643
- const [isLive, setIsLive] = useState(false);
644
- const [isVisible, setIsVisible] = useState(false);
645
- const intervalRef = useRef5(null);
646
- const { enabled = true, onLiveStateChange } = options;
647
- const checkLiveStatus = () => {
648
- if (!playerRef.current || !enabled) {
649
- return;
1600
+ // src/hooks/usePosterFallback.ts
1601
+ import { useEffect, useState as useState2 } from "react";
1602
+
1603
+ // src/hooks/useLiveIndicator.ts
1604
+ import { useEffect as useEffect2, useRef as useRef6 } from "react";
1605
+ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1606
+ const observerRef = useRef6(null);
1607
+ const intervalRef = useRef6(null);
1608
+ const lastStatusRef = useRef6(null);
1609
+ const {
1610
+ enabled = true,
1611
+ indicatorColor = "#ff0000",
1612
+ indicatorSize = 8,
1613
+ showPulseAnimation = true,
1614
+ liveThresholdSeconds = 15,
1615
+ onLiveStatusChange
1616
+ } = options;
1617
+ const getLiveStatus = (player) => {
1618
+ if (!player) {
1619
+ return { isLive: false, isNearEdge: false };
650
1620
  }
651
1621
  try {
652
- const player = playerRef.current;
653
- if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
654
- return;
1622
+ if (!player.getManifest || typeof player.getManifest !== "function") {
1623
+ return { isLive: false, isNearEdge: false };
655
1624
  }
656
1625
  const manifest = player.getManifest();
657
1626
  if (!manifest) {
658
- return;
1627
+ return { isLive: false, isNearEdge: false };
659
1628
  }
660
- const timeline = player.getPresentationTimeline();
1629
+ const timeline = manifest.presentationTimeline;
661
1630
  if (!timeline || typeof timeline.isLive !== "function") {
662
- return;
663
- }
664
- const liveStatus = timeline.isLive();
665
- if (liveStatus !== isLive) {
666
- setIsLive(liveStatus);
667
- setIsVisible(liveStatus);
668
- onLiveStateChange?.(liveStatus);
1631
+ return { isLive: false, isNearEdge: false };
669
1632
  }
1633
+ const isLiveStream = timeline.isLive();
1634
+ if (!isLiveStream) return { isLive: false, isNearEdge: false };
1635
+ const videoElement = player.getMediaElement?.();
1636
+ if (!videoElement) return { isLive: true, isNearEdge: false };
1637
+ const liveEdge = timeline.getSeekRangeEnd?.() ?? timeline.getSegmentAvailabilityEnd?.();
1638
+ if (liveEdge === void 0) return { isLive: true, isNearEdge: false };
1639
+ const currentTime = videoElement.currentTime;
1640
+ const timeBehindLive = liveEdge - currentTime;
1641
+ return {
1642
+ isLive: true,
1643
+ isNearEdge: timeBehindLive <= liveThresholdSeconds,
1644
+ liveEdge
1645
+ };
670
1646
  } catch (error) {
671
- if (error instanceof Error && !error.message.includes("not a function")) {
672
- console.error("Error checking live status:", error);
673
- }
1647
+ console.error("Error checking live status:", error);
1648
+ return { isLive: false, isNearEdge: false };
674
1649
  }
675
1650
  };
676
- useEffect(() => {
677
- if (!enabled) {
678
- setIsLive(false);
679
- setIsVisible(false);
680
- return;
681
- }
682
- checkLiveStatus();
683
- intervalRef.current = setInterval(checkLiveStatus, 2e3);
684
- return () => {
685
- if (intervalRef.current) {
686
- clearInterval(intervalRef.current);
687
- intervalRef.current = null;
688
- }
689
- };
690
- }, [enabled, playerRef.current]);
691
- useEffect(() => {
692
- return () => {
693
- if (intervalRef.current) {
694
- clearInterval(intervalRef.current);
1651
+ const seekToLiveEdge = () => {
1652
+ const player = playerRef.current;
1653
+ if (!player) return;
1654
+ try {
1655
+ const manifest = player.getManifest();
1656
+ if (!manifest) return;
1657
+ const timeline = manifest.presentationTimeline;
1658
+ const liveEdge = timeline?.getSeekRangeEnd?.() ?? timeline?.getSegmentAvailabilityEnd?.();
1659
+ if (liveEdge !== void 0) {
1660
+ const videoElement = player.getMediaElement?.();
1661
+ if (videoElement) {
1662
+ videoElement.currentTime = liveEdge;
1663
+ }
695
1664
  }
696
- };
697
- }, []);
698
- const hideBadge = () => setIsVisible(false);
699
- const showBadge = () => setIsVisible(true);
700
- return {
701
- isLive,
702
- isVisible,
703
- hideBadge,
704
- showBadge,
705
- checkLiveStatus
1665
+ } catch (error) {
1666
+ console.error("Error seeking to live edge:", error);
1667
+ }
706
1668
  };
707
- };
708
-
709
- // src/hooks/usePosterFallback.ts
710
- import { useEffect as useEffect2, useState as useState2 } from "react";
711
-
712
- // src/hooks/useLiveIndicator.ts
713
- import { useEffect as useEffect3, useRef as useRef7 } from "react";
714
- var useLiveIndicator = (containerRef, options = {}) => {
715
- const observerRef = useRef7(null);
716
- const {
717
- enabled = true,
718
- indicatorColor = "#ff0000",
719
- indicatorSize = 8,
720
- showPulseAnimation = true
721
- } = options;
722
- useEffect3(() => {
1669
+ useEffect2(() => {
723
1670
  if (!containerRef.current || !enabled) {
724
1671
  return;
725
1672
  }
726
- const addLiveIndicator = (currentTimeElement) => {
727
- if (currentTimeElement.querySelector(".live-indicator-dot")) {
1673
+ const updateLiveIndicator = (currentTimeElement, status) => {
1674
+ const parent = currentTimeElement.parentElement;
1675
+ if (!parent) return;
1676
+ const existingContainer = parent.querySelector(".live-indicator-container");
1677
+ const isCurrentlyNearEdge = existingContainer?.getAttribute("data-near-edge") === "true";
1678
+ if (existingContainer && status.isNearEdge === isCurrentlyNearEdge) {
728
1679
  return;
729
1680
  }
1681
+ if (existingContainer) {
1682
+ existingContainer.remove();
1683
+ }
1684
+ const container = document.createElement("span");
1685
+ container.className = "live-indicator-container";
1686
+ container.setAttribute("data-near-edge", status.isNearEdge.toString());
1687
+ container.style.cssText = `
1688
+ display: inline-flex;
1689
+ align-items: center;
1690
+ width: 80px;
1691
+ ${!status.isNearEdge ? "cursor: pointer;" : ""}
1692
+ `;
730
1693
  const indicator = document.createElement("span");
731
1694
  indicator.className = "live-indicator-dot";
732
1695
  indicator.style.cssText = `
733
1696
  display: inline-block;
734
1697
  width: ${indicatorSize}px;
735
1698
  height: ${indicatorSize}px;
736
- background-color: ${indicatorColor};
1699
+ background-color: ${status.isNearEdge ? indicatorColor : "#888888"};
737
1700
  border-radius: 50%;
738
1701
  margin-right: 6px;
739
- vertical-align: middle;
740
- ${showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
1702
+ ${status.isNearEdge && showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
741
1703
  `;
742
- currentTimeElement.insertBefore(indicator, currentTimeElement.firstChild);
1704
+ const liveText = document.createElement("span");
1705
+ liveText.className = "live-indicator-text";
1706
+ liveText.textContent = status.isNearEdge ? "LIVE" : "GO TO LIVE";
1707
+ container.appendChild(indicator);
1708
+ container.appendChild(liveText);
1709
+ if (!status.isNearEdge) {
1710
+ container.addEventListener("click", seekToLiveEdge);
1711
+ }
1712
+ if (status.isNearEdge) {
1713
+ parent.insertBefore(container, currentTimeElement);
1714
+ currentTimeElement.style.display = "none";
1715
+ } else {
1716
+ currentTimeElement.insertAdjacentElement("afterend", container);
1717
+ currentTimeElement.style.display = "";
1718
+ }
743
1719
  };
744
1720
  const removeLiveIndicator = (currentTimeElement) => {
745
- const indicator = currentTimeElement.querySelector(".live-indicator-dot");
746
- if (indicator) {
747
- indicator.remove();
1721
+ const parent = currentTimeElement.parentElement;
1722
+ if (!parent) return;
1723
+ const container = parent.querySelector(".live-indicator-container");
1724
+ if (container) {
1725
+ container.remove();
1726
+ currentTimeElement.style.display = "";
748
1727
  }
749
1728
  };
750
1729
  const checkForLiveContent = () => {
751
1730
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1731
+ const status = getLiveStatus(playerRef.current);
1732
+ const lastStatus = lastStatusRef.current;
1733
+ if (onLiveStatusChange && (!lastStatus || lastStatus.isLive !== status.isLive || lastStatus.isNearEdge !== status.isNearEdge)) {
1734
+ onLiveStatusChange(status);
1735
+ lastStatusRef.current = { isLive: status.isLive, isNearEdge: status.isNearEdge };
1736
+ }
752
1737
  currentTimeElements?.forEach((element) => {
753
- const textContent = element.textContent?.trim() || "";
754
- if (textContent.toLowerCase().includes("live")) {
755
- addLiveIndicator(element);
1738
+ if (status.isLive) {
1739
+ updateLiveIndicator(element, status);
756
1740
  } else {
757
1741
  removeLiveIndicator(element);
758
1742
  }
759
1743
  });
760
1744
  };
761
1745
  checkForLiveContent();
1746
+ intervalRef.current = setInterval(checkForLiveContent, 1e3);
762
1747
  observerRef.current = new MutationObserver((mutations) => {
763
1748
  let shouldCheck = false;
764
1749
  mutations.forEach((mutation) => {
@@ -784,31 +1769,289 @@ var useLiveIndicator = (containerRef, options = {}) => {
784
1769
  characterData: true,
785
1770
  characterDataOldValue: true
786
1771
  });
787
- const intervalId = setInterval(checkForLiveContent, 1e3);
788
1772
  return () => {
789
1773
  if (observerRef.current) {
790
1774
  observerRef.current.disconnect();
791
1775
  }
792
- clearInterval(intervalId);
1776
+ if (intervalRef.current) {
1777
+ clearInterval(intervalRef.current);
1778
+ }
793
1779
  };
794
- }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
1780
+ }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
795
1781
  return {
796
- // Expose method to manually trigger check if needed
797
- checkForLiveContent: () => {
798
- const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
799
- currentTimeElements?.forEach((element) => {
800
- const textContent = element.textContent?.trim() || "";
801
- if (textContent.toLowerCase().includes("live")) {
1782
+ seekToLiveEdge,
1783
+ getLiveStatus: () => getLiveStatus(playerRef.current)
1784
+ };
1785
+ };
1786
+
1787
+ // src/hooks/useKeyboardControls.ts
1788
+ import { useCallback as useCallback7, useEffect as useEffect3 } from "react";
1789
+ var useKeyboardControls = (videoRef, options = {}) => {
1790
+ const { skipBack, skipForward, enabled = true } = options;
1791
+ const isDesktop = useCallback7(() => {
1792
+ return window.innerWidth > 767 && !/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1793
+ }, []);
1794
+ const handleKeydown = useCallback7((event) => {
1795
+ if (!enabled || !isDesktop() || !videoRef.current) return;
1796
+ const activeElement = document.activeElement;
1797
+ if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)) {
1798
+ return;
1799
+ }
1800
+ switch (event.key) {
1801
+ case "ArrowLeft":
1802
+ event.preventDefault();
1803
+ skipBack?.();
1804
+ break;
1805
+ case "ArrowRight":
1806
+ event.preventDefault();
1807
+ skipForward?.();
1808
+ break;
1809
+ case " ":
1810
+ case "Space":
1811
+ event.preventDefault();
1812
+ if (videoRef.current.paused) {
1813
+ videoRef.current.play();
1814
+ } else {
1815
+ videoRef.current.pause();
802
1816
  }
1817
+ break;
1818
+ }
1819
+ }, [enabled, videoRef, skipBack, skipForward, isDesktop]);
1820
+ useEffect3(() => {
1821
+ if (!enabled || !isDesktop()) return;
1822
+ document.addEventListener("keydown", handleKeydown);
1823
+ return () => {
1824
+ document.removeEventListener("keydown", handleKeydown);
1825
+ };
1826
+ }, [handleKeydown, enabled, isDesktop]);
1827
+ return {
1828
+ isDesktop: isDesktop()
1829
+ };
1830
+ };
1831
+
1832
+ // src/hooks/useAdEvents.ts
1833
+ import { useCallback as useCallback8, useRef as useRef7 } from "react";
1834
+ var useAdEvents = (playerRef, handlers) => {
1835
+ const listenersRef = useRef7([]);
1836
+ const setupAdEventListeners = useCallback8(() => {
1837
+ const player = playerRef.current;
1838
+ if (!player) return;
1839
+ const adManager = player.getAdManager();
1840
+ if (!adManager) return;
1841
+ const onAdsManagerLoaded = (event) => {
1842
+ const adsManager = event.getAdsManager();
1843
+ const onAdStarted = () => {
1844
+ console.log("Ad started");
1845
+ handlers.onAdStart?.();
1846
+ };
1847
+ const onAdComplete = () => {
1848
+ console.log("Ad completed");
1849
+ handlers.onAdComplete?.();
1850
+ };
1851
+ const onAdError = (adErrorEvent) => {
1852
+ console.error("Ad error:", adErrorEvent.getError());
1853
+ handlers.onAdError?.(adErrorEvent.getError());
1854
+ };
1855
+ const onAdSkipped = () => {
1856
+ console.log("Ad skipped");
1857
+ handlers.onAdSkipped?.();
1858
+ };
1859
+ const onAdPaused = () => {
1860
+ console.log("Ad paused");
1861
+ handlers.onAdPaused?.();
1862
+ };
1863
+ const onAdResumed = () => {
1864
+ console.log("Ad resumed");
1865
+ handlers.onAdResumed?.();
1866
+ };
1867
+ const onAdProgress = (adProgressData) => {
1868
+ handlers.onAdProgress?.(adProgressData);
1869
+ };
1870
+ const onAllAdsCompleted = () => {
1871
+ console.log("All ads completed");
1872
+ handlers.onAllAdsCompleted?.();
1873
+ };
1874
+ const adEventListeners = [];
1875
+ if (window.google?.ima) {
1876
+ const AdEvent = window.google.ima.AdEvent.Type;
1877
+ const AdErrorEvent = window.google.ima.AdErrorEvent.Type;
1878
+ if (handlers.onAdStart) {
1879
+ adsManager.addEventListener(AdEvent.STARTED, onAdStarted);
1880
+ adEventListeners.push({ event: AdEvent.STARTED, listener: onAdStarted });
1881
+ }
1882
+ if (handlers.onAdComplete) {
1883
+ adsManager.addEventListener(AdEvent.COMPLETE, onAdComplete);
1884
+ adEventListeners.push({ event: AdEvent.COMPLETE, listener: onAdComplete });
1885
+ }
1886
+ if (handlers.onAdError) {
1887
+ adsManager.addEventListener(AdErrorEvent.AD_ERROR, onAdError);
1888
+ adEventListeners.push({ event: AdErrorEvent.AD_ERROR, listener: onAdError });
1889
+ }
1890
+ if (handlers.onAdSkipped) {
1891
+ adsManager.addEventListener(AdEvent.SKIPPED, onAdSkipped);
1892
+ adEventListeners.push({ event: AdEvent.SKIPPED, listener: onAdSkipped });
1893
+ }
1894
+ if (handlers.onAdPaused) {
1895
+ adsManager.addEventListener(AdEvent.PAUSED, onAdPaused);
1896
+ adEventListeners.push({ event: AdEvent.PAUSED, listener: onAdPaused });
1897
+ }
1898
+ if (handlers.onAdResumed) {
1899
+ adsManager.addEventListener(AdEvent.RESUMED, onAdResumed);
1900
+ adEventListeners.push({ event: AdEvent.RESUMED, listener: onAdResumed });
1901
+ }
1902
+ if (handlers.onAdProgress) {
1903
+ adsManager.addEventListener(AdEvent.AD_PROGRESS, onAdProgress);
1904
+ adEventListeners.push({ event: AdEvent.AD_PROGRESS, listener: onAdProgress });
1905
+ }
1906
+ if (handlers.onAllAdsCompleted) {
1907
+ adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, onAllAdsCompleted);
1908
+ adEventListeners.push({ event: AdEvent.ALL_ADS_COMPLETED, listener: onAllAdsCompleted });
1909
+ }
1910
+ listenersRef.current.push({
1911
+ adsManager,
1912
+ listeners: adEventListeners
1913
+ });
1914
+ }
1915
+ };
1916
+ try {
1917
+ player.addEventListener("ad-started", () => {
1918
+ console.log("Shaka ad-started event");
1919
+ handlers.onAdStart?.();
1920
+ });
1921
+ player.addEventListener("ad-complete", () => {
1922
+ console.log("Shaka ad-complete event");
1923
+ handlers.onAdComplete?.();
1924
+ });
1925
+ player.addEventListener("ad-skipped", () => {
1926
+ console.log("Shaka ad-skipped event");
1927
+ handlers.onAdSkipped?.();
1928
+ });
1929
+ player.addEventListener("ad-error", (event) => {
1930
+ console.error("Shaka ad-error event:", event);
1931
+ handlers.onAdError?.(event);
1932
+ });
1933
+ listenersRef.current.push({
1934
+ type: "shaka",
1935
+ player,
1936
+ events: ["ad-started", "ad-complete", "ad-skipped", "ad-error"]
803
1937
  });
1938
+ } catch (error) {
1939
+ console.warn("Error setting up ad event listeners:", error);
1940
+ }
1941
+ }, [playerRef, handlers]);
1942
+ const cleanupAdEventListeners = useCallback8(() => {
1943
+ try {
1944
+ listenersRef.current.forEach((listenerGroup) => {
1945
+ if (listenerGroup.type === "shaka" && listenerGroup.player) {
1946
+ listenerGroup.events.forEach((eventName) => {
1947
+ try {
1948
+ listenerGroup.player.removeEventListener(eventName, () => {
1949
+ });
1950
+ } catch (e) {
1951
+ console.warn(`Error removing ${eventName} listener:`, e);
1952
+ }
1953
+ });
1954
+ } else if (listenerGroup.adsManager && listenerGroup.listeners) {
1955
+ listenerGroup.listeners.forEach(({ event, listener }) => {
1956
+ try {
1957
+ listenerGroup.adsManager.removeEventListener(event, listener);
1958
+ } catch (e) {
1959
+ console.warn("Error removing ad listener:", e);
1960
+ }
1961
+ });
1962
+ }
1963
+ });
1964
+ listenersRef.current = [];
1965
+ } catch (error) {
1966
+ console.warn("Error cleaning up ad event listeners:", error);
804
1967
  }
1968
+ }, []);
1969
+ return {
1970
+ setupAdEventListeners,
1971
+ cleanupAdEventListeners
805
1972
  };
806
1973
  };
807
1974
 
1975
+ // src/Player.tsx
1976
+ import { twMerge as twMerge2 } from "tailwind-merge";
1977
+
1978
+ // src/utils/scriptLoader.ts
1979
+ var SCRIPT_CONFIGS = {
1980
+ ima: {
1981
+ src: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
1982
+ id: "ima-sdk",
1983
+ type: "text/javascript"
1984
+ },
1985
+ system73: {
1986
+ src: "//cdn.s73cloud.com/4/s73-sdk-shakaplayer.js",
1987
+ id: "system73-sdk",
1988
+ type: "application/javascript"
1989
+ }
1990
+ };
1991
+ function loadScript(config) {
1992
+ return new Promise((resolve, reject) => {
1993
+ if (document.getElementById(config.id)) {
1994
+ resolve();
1995
+ return;
1996
+ }
1997
+ const script = document.createElement("script");
1998
+ script.id = config.id;
1999
+ script.src = config.src;
2000
+ script.type = config.type || "text/javascript";
2001
+ script.async = true;
2002
+ script.onload = () => resolve();
2003
+ script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
2004
+ document.head.appendChild(script);
2005
+ });
2006
+ }
2007
+ function getRequiredScriptLoaders(needsIma, needsSystem73) {
2008
+ const loaders = [];
2009
+ if (needsIma) {
2010
+ loaders.push(loadScript(SCRIPT_CONFIGS.ima));
2011
+ }
2012
+ if (needsSystem73) {
2013
+ loaders.push(loadScript(SCRIPT_CONFIGS.system73));
2014
+ }
2015
+ return loaders;
2016
+ }
2017
+ async function loadScripts(scriptLoaders) {
2018
+ if (scriptLoaders.length === 0) {
2019
+ return;
2020
+ }
2021
+ try {
2022
+ await Promise.all(scriptLoaders);
2023
+ } catch (error) {
2024
+ console.error("Error loading scripts:", error);
2025
+ throw error;
2026
+ }
2027
+ }
2028
+ function waitForGlobal(globalName, timeout = 5e3) {
2029
+ return new Promise((resolve, reject) => {
2030
+ const startTime = Date.now();
2031
+ function checkGlobal() {
2032
+ const global = window[globalName];
2033
+ if (global) {
2034
+ resolve(global);
2035
+ return;
2036
+ }
2037
+ if (Date.now() - startTime > timeout) {
2038
+ reject(new Error(`Timeout waiting for global: ${globalName}`));
2039
+ return;
2040
+ }
2041
+ setTimeout(checkGlobal, 100);
2042
+ }
2043
+ checkGlobal();
2044
+ });
2045
+ }
2046
+ async function waitForGlobals(globalNames, timeout = 5e3) {
2047
+ const promises = globalNames.map((name) => waitForGlobal(name, timeout));
2048
+ await Promise.all(promises);
2049
+ }
2050
+
808
2051
  // src/components/Loading.tsx
809
2052
  import { twMerge } from "tailwind-merge";
810
- import { jsx, jsxs } from "react/jsx-runtime";
811
- var Loading = ({ className }) => /* @__PURE__ */ jsxs(
2053
+ import { jsx as jsx4 } from "react/jsx-runtime";
2054
+ var Loading = ({ className }) => /* @__PURE__ */ jsx4(
812
2055
  "div",
813
2056
  {
814
2057
  className: twMerge(
@@ -816,17 +2059,36 @@ var Loading = ({ className }) => /* @__PURE__ */ jsxs(
816
2059
  className
817
2060
  ),
818
2061
  role: "status",
819
- children: [
820
- /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-white" }),
821
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading..." })
822
- ]
2062
+ children: /* @__PURE__ */ jsx4("div", { className: " flex justify-center items-center", children: /* @__PURE__ */ jsx4(
2063
+ "svg",
2064
+ {
2065
+ className: "shaka-spinner-svg animate-spin h-12 w-12",
2066
+ viewBox: "0 0 64 64",
2067
+ xmlns: "http://www.w3.org/2000/svg",
2068
+ children: /* @__PURE__ */ jsx4(
2069
+ "circle",
2070
+ {
2071
+ className: "shaka-spinner-path",
2072
+ cx: "32",
2073
+ cy: "32",
2074
+ r: "28",
2075
+ strokeWidth: "4",
2076
+ strokeLinecap: "round",
2077
+ stroke: "currentColor",
2078
+ fill: "none",
2079
+ strokeDasharray: "176",
2080
+ strokeDashoffset: "120"
2081
+ }
2082
+ )
2083
+ }
2084
+ ) })
823
2085
  }
824
2086
  );
825
2087
 
826
2088
  // src/components/ErrorScreen.tsx
827
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
828
- var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { className: "w-full h-full md:rounded-2xl! aspect-video bg-black", children: /* @__PURE__ */ jsxs2("div", { className: "bg-[#151515] text-white w-full h-full flex justify-stretch items-center", children: [
829
- /* @__PURE__ */ jsx2(
2089
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2090
+ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx5("div", { className: "w-full h-full md:rounded-2xl! aspect-video bg-black flex", children: /* @__PURE__ */ jsxs3("div", { className: "bg-[#151515] text-white w-full h-full flex justify-center items-center", children: [
2091
+ /* @__PURE__ */ jsx5(
830
2092
  "svg",
831
2093
  {
832
2094
  className: "w-24 h-24 m-6",
@@ -836,7 +2098,7 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { clas
836
2098
  style: { width: 96 },
837
2099
  viewBox: "0 0 24 24",
838
2100
  xmlns: "http://www.w3.org/2000/svg",
839
- children: /* @__PURE__ */ jsx2(
2101
+ children: /* @__PURE__ */ jsx5(
840
2102
  "path",
841
2103
  {
842
2104
  d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z",
@@ -846,66 +2108,22 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ jsx2("div", { clas
846
2108
  )
847
2109
  }
848
2110
  ),
849
- /* @__PURE__ */ jsxs2("div", { children: [
850
- /* @__PURE__ */ jsx2("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
851
- /* @__PURE__ */ jsx2("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
2111
+ /* @__PURE__ */ jsxs3("div", { children: [
2112
+ /* @__PURE__ */ jsx5("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
2113
+ /* @__PURE__ */ jsx5("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
852
2114
  ] })
853
2115
  ] }) });
854
2116
 
855
2117
  // src/components/Title.tsx
856
- import { jsx as jsx3 } from "react/jsx-runtime";
857
- var Title = ({ title }) => /* @__PURE__ */ jsx3("div", { className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4", children: /* @__PURE__ */ jsx3("h2", { className: "text-white text-xl font-semibold", children: title }) });
858
-
859
- // src/components/LiveBadge.tsx
860
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
861
- var LiveBadge = ({
862
- isVisible,
863
- position = "top-right",
864
- className = "",
865
- style = {},
866
- text = "LIVE"
867
- }) => {
868
- if (!isVisible) return null;
869
- const positionClasses = {
870
- "top-left": "top-4 left-4",
871
- "top-right": "top-4 right-4",
872
- "bottom-left": "bottom-4 left-4",
873
- "bottom-right": "bottom-4 right-4"
874
- };
875
- return /* @__PURE__ */ jsx4(
876
- "div",
877
- {
878
- className: `
879
- absolute z-50
880
- ${positionClasses[position]}
881
- bg-red-600 text-white
882
- px-2 py-1
883
- rounded-md
884
- text-xs font-bold
885
- uppercase tracking-wide
886
- shadow-lg
887
- animate-pulse
888
- pointer-events-none
889
- ${className}
890
- `,
891
- style,
892
- children: /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1", children: [
893
- /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 bg-white rounded-full animate-pulse" }),
894
- text
895
- ] })
896
- }
897
- );
898
- };
899
-
900
- // src/styles.css
901
- 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-8 {\n height: calc(var(--spacing) * 8);\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-8 {\n width: calc(var(--spacing) * 8);\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 .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\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@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\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-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-border-style: solid;\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-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
2118
+ import { jsx as jsx6 } from "react/jsx-runtime";
2119
+ var Title = ({ title }) => /* @__PURE__ */ jsx6("div", { className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4", children: /* @__PURE__ */ jsx6("h2", { className: "text-white text-xl font-semibold", children: title }) });
902
2120
 
903
2121
  // src/Player.tsx
904
- import { twMerge as twMerge2 } from "tailwind-merge";
905
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2122
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
906
2123
  var Player = forwardRef(
907
2124
  ({
908
2125
  src,
2126
+ managedMode = false,
909
2127
  autoPlay = false,
910
2128
  loop = false,
911
2129
  muted = false,
@@ -917,25 +2135,48 @@ var Player = forwardRef(
917
2135
  shakaConfig,
918
2136
  drmConfig,
919
2137
  muxConfig,
2138
+ system73Config,
920
2139
  imaConfig,
921
2140
  chromecastConfig,
922
2141
  qualityConfig,
923
2142
  seekbarConfig,
2143
+ iconSizes,
924
2144
  events,
2145
+ locale = "en",
925
2146
  containerClassName,
926
- ...props
2147
+ liveThresholdSeconds = 15,
2148
+ publicKey,
2149
+ auth,
2150
+ ...videoProps
927
2151
  }, ref) => {
928
2152
  const videoRef = useRef8(null);
929
2153
  const containerRef = useRef8(null);
930
- const adContainerRef = useRef8(null);
2154
+ const [isScriptsLoaded, setIsScriptsLoaded] = useState3(false);
2155
+ const [isInitialLoading, setIsInitialLoading] = useState3(true);
2156
+ const [bfResetKey, setBfResetKey] = useState3(0);
2157
+ const hasPlaylist = !!src && (typeof src === "string" || !!(src.url || src.drm?.widevine?.playlistUrl || src.drm?.playready?.playlistUrl || src.drm?.fairplay?.playlistUrl));
931
2158
  useImperativeHandle(ref, () => videoRef.current, []);
932
- const { playerRef, initializePlayer, destroyPlayer } = useShakePlayer({
2159
+ const { playerRef, initializePlayer, loadManifest, destroyPlayer, isRetrying } = useShakaPlayer({
933
2160
  src,
934
2161
  shakaConfig,
935
2162
  drmConfig,
936
2163
  onError: events?.onError,
937
- onPlayerReady: events?.onPlayerReady
2164
+ onPlayerReady: events?.onPlayerReady,
2165
+ muxConfig,
2166
+ onMuxReady: events?.onMuxReady,
2167
+ onMuxDataUpdate: events?.onMuxDataUpdate,
2168
+ publicKey,
2169
+ mottoToken: auth?.mottoToken,
2170
+ hasAds: !!imaConfig?.adTagUrl,
2171
+ hasSystem73: !!system73Config?.apiKey,
2172
+ apiToken: auth?.apiToken
938
2173
  });
2174
+ const {
2175
+ initializeMux,
2176
+ updateMuxData,
2177
+ handleMuxError,
2178
+ destroyMux
2179
+ } = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
939
2180
  const {
940
2181
  getAvailableQualities,
941
2182
  setQuality,
@@ -948,12 +2189,11 @@ var Player = forwardRef(
948
2189
  skipDuration,
949
2190
  shouldShowSkipControls
950
2191
  } = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
951
- const {
952
- initializeMux,
953
- updateMuxData,
954
- handleMuxError,
955
- destroyMux
956
- } = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
2192
+ useKeyboardControls(videoRef, {
2193
+ skipBack,
2194
+ skipForward,
2195
+ enabled: true
2196
+ });
957
2197
  const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
958
2198
  onPlay: events?.onPlay,
959
2199
  onPause: events?.onPause,
@@ -969,109 +2209,230 @@ var Player = forwardRef(
969
2209
  chromecastConfig,
970
2210
  seekbarConfig,
971
2211
  events?.onSkipBack,
972
- events?.onSkipForward
2212
+ events?.onSkipForward,
2213
+ iconSizes,
2214
+ locale
973
2215
  );
974
- const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
975
- enabled: true,
976
- onLiveStateChange: (isLive2) => {
977
- events?.onLiveStateChange?.(isLive2);
978
- }
979
- });
980
- useLiveIndicator(containerRef, {
2216
+ const { getLiveStatus, seekToLiveEdge } = useLiveIndicator(containerRef, playerRef, {
981
2217
  enabled: true,
982
2218
  indicatorColor: "#ff0000",
983
2219
  indicatorSize: 8,
984
- showPulseAnimation: true
2220
+ showPulseAnimation: true,
2221
+ liveThresholdSeconds,
2222
+ onLiveStatusChange: events?.onLiveStatusChange
985
2223
  });
986
- const initializeAds = () => {
987
- if (!imaConfig || !playerRef.current || !videoRef.current) return;
988
- const adManager = playerRef.current.getAdManager();
989
- if (!adManager) return;
990
- adManager.addEventListener(shaka2.ads?.Utils?.AD_STARTED, () => {
991
- events?.onAdStart?.();
992
- });
993
- adManager.addEventListener(shaka2.ads?.Utils?.AD_COMPLETE, () => {
994
- events?.onAdComplete?.();
995
- });
996
- adManager.addEventListener(shaka2.ads?.Utils?.AD_ERROR, (event) => {
997
- events?.onAdError?.(event.detail);
998
- });
999
- if (imaConfig.adTagUrl) {
1000
- const adContainer = adContainerRef.current;
1001
- if (adContainer) {
1002
- adManager.initClientSide(adContainer, videoRef.current, imaConfig.adsRenderingSettings);
1003
- const adsRequest = {
1004
- adTagUrl: imaConfig.adTagUrl,
1005
- linearAdSlotWidth: imaConfig.linearAdSlotWidth || width || 640,
1006
- linearAdSlotHeight: imaConfig.linearAdSlotHeight || height || 360,
1007
- nonLinearAdSlotWidth: imaConfig.nonLinearAdSlotWidth || width || 640,
1008
- nonLinearAdSlotHeight: imaConfig.nonLinearAdSlotHeight || 150
1009
- };
1010
- adManager.requestClientSideAds(adsRequest);
1011
- }
2224
+ const { setupAdEventListeners, cleanupAdEventListeners } = useAdEvents(playerRef, {
2225
+ onAdStart: events?.onAdStart,
2226
+ onAdComplete: events?.onAdComplete,
2227
+ onAdError: events?.onAdError,
2228
+ onAdSkipped: events?.onAdSkipped,
2229
+ onAdPaused: events?.onAdPaused,
2230
+ onAdResumed: events?.onAdResumed,
2231
+ onAdProgress: events?.onAdProgress,
2232
+ onAllAdsCompleted: events?.onAllAdsCompleted
2233
+ });
2234
+ const initializeSystem73 = useCallback9((playerConfig) => {
2235
+ if (!system73Config?.apiKey || !window.S73ShakaPlayerWrapper) {
2236
+ return null;
1012
2237
  }
1013
- };
1014
- const initializeChromecast = () => {
1015
- if (!chromecastConfig?.enabled) {
2238
+ console.log("Initializing System73 SDK...");
2239
+ try {
2240
+ const s73Config = {
2241
+ apiKey: system73Config.apiKey,
2242
+ contentSteeringEndpoint: system73Config.contentSteeringEndpoint,
2243
+ channelId: system73Config.channelId
2244
+ };
2245
+ const wrapper = window.S73ShakaPlayerWrapper(s73Config, { shaka: shaka3 });
2246
+ wrapper.wrapPlayerConfig(playerConfig);
2247
+ console.log("System73 SDK initialized with config:", s73Config);
2248
+ return wrapper;
2249
+ } catch (error) {
2250
+ console.error("Error initializing System73 SDK:", error);
2251
+ return null;
2252
+ }
2253
+ }, [system73Config]);
2254
+ const initializeAds = useCallback9(async () => {
2255
+ if (!imaConfig?.adTagUrl || !playerRef.current || !videoRef.current || !uiRef.current) {
2256
+ return;
2257
+ }
2258
+ if (!window.google?.ima) {
2259
+ console.error("Google IMA SDK not available when trying to initialize ads");
1016
2260
  return;
1017
2261
  }
1018
2262
  try {
1019
- if (events?.onCastStateChange) {
1020
- setTimeout(() => events.onCastStateChange(false), 100);
2263
+ const player = playerRef.current;
2264
+ const video = videoRef.current;
2265
+ const ui = uiRef.current;
2266
+ const controls2 = ui.getControls();
2267
+ const container = controls2.getClientSideAdContainer();
2268
+ const adManager = player.getAdManager();
2269
+ if (!adManager) {
2270
+ console.error("Ad manager not available");
2271
+ return;
1021
2272
  }
2273
+ const google = window.google;
2274
+ let adsRenderingSettings = null;
2275
+ if (imaConfig.adsRenderingSettings) {
2276
+ adsRenderingSettings = imaConfig.adsRenderingSettings;
2277
+ } else if (autoPlay) {
2278
+ adsRenderingSettings = new google.ima.AdsRenderingSettings();
2279
+ adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
2280
+ }
2281
+ adManager.initClientSide(container, video, adsRenderingSettings);
2282
+ const adsRequest = new google.ima.AdsRequest();
2283
+ adsRequest.adTagUrl = imaConfig.adTagUrl;
2284
+ adManager.requestClientSideAds(adsRequest);
2285
+ setupAdEventListeners();
2286
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2287
+ await loadManifest();
1022
2288
  } catch (error) {
1023
- console.warn("Chromecast initialization failed:", error);
2289
+ console.error("Error initializing ads:", error);
1024
2290
  }
1025
- };
2291
+ }, [imaConfig, autoPlay, setupAdEventListeners, loadManifest]);
2292
+ useEffect4(() => {
2293
+ const loadRequiredScripts = async () => {
2294
+ try {
2295
+ const scriptLoaders = getRequiredScriptLoaders(!!imaConfig?.adTagUrl, !!system73Config?.apiKey);
2296
+ await loadScripts(scriptLoaders);
2297
+ const globalsToWait = [];
2298
+ if (imaConfig?.adTagUrl) {
2299
+ globalsToWait.push("google");
2300
+ }
2301
+ if (system73Config?.apiKey) {
2302
+ globalsToWait.push("S73ShakaPlayerWrapper");
2303
+ }
2304
+ if (globalsToWait.length > 0) {
2305
+ await waitForGlobals(globalsToWait);
2306
+ }
2307
+ setIsScriptsLoaded(true);
2308
+ } catch (error) {
2309
+ console.error("Error loading required scripts:", error);
2310
+ setIsScriptsLoaded(true);
2311
+ }
2312
+ };
2313
+ loadRequiredScripts();
2314
+ }, [imaConfig?.adTagUrl, system73Config?.apiKey]);
2315
+ useEffect4(() => {
2316
+ const onPageShow = (e) => {
2317
+ if (e && e.persisted) {
2318
+ setBfResetKey((k) => k + 1);
2319
+ }
2320
+ };
2321
+ window.addEventListener("pageshow", onPageShow);
2322
+ return () => window.removeEventListener("pageshow", onPageShow);
2323
+ }, []);
1026
2324
  useEffect4(() => {
1027
2325
  const video = videoRef.current;
1028
- if (!video) return;
2326
+ if (!video || !isScriptsLoaded) return;
1029
2327
  const initialize = async () => {
1030
2328
  try {
2329
+ console.log("\u{1F680} [Player] Starting initialization...");
2330
+ setIsInitialLoading(true);
2331
+ let system73Wrapper = null;
2332
+ if (system73Config?.apiKey && window.S73ShakaPlayerWrapper) {
2333
+ console.log("\u{1F4E6} [System73] Step 1: Initializing System73 wrapper with config");
2334
+ const playerConfig = { ...shakaConfig };
2335
+ system73Wrapper = initializeSystem73(playerConfig);
2336
+ if (system73Wrapper) {
2337
+ shakaConfig = playerConfig;
2338
+ console.log("\u2705 [System73] Step 1 complete: Wrapper created and config modified");
2339
+ }
2340
+ }
2341
+ console.log("\u{1F3AC} [Shaka] Step 2: Initializing Shaka Player (auto-load:", !system73Config?.apiKey && !imaConfig?.adTagUrl, ")");
1031
2342
  await initializePlayer(video);
2343
+ console.log("\u2705 [Shaka] Step 2 complete: Player initialized");
2344
+ if (system73Wrapper && playerRef.current) {
2345
+ console.log("\u{1F517} [System73] Step 3: Wrapping Shaka player with System73");
2346
+ system73Wrapper.wrapPlayer(playerRef.current);
2347
+ console.log("\u2705 [System73] Step 3 complete: Player wrapped");
2348
+ if (!imaConfig?.adTagUrl) {
2349
+ console.log("\u{1F4FA} [System73] Step 4: Loading manifest");
2350
+ await loadManifest();
2351
+ console.log("\u2705 [System73] Step 4 complete: Manifest loaded");
2352
+ } else {
2353
+ console.log("\u23ED\uFE0F [System73] Skipping manifest load - ads will handle it");
2354
+ }
2355
+ }
2356
+ console.log("\u{1F4CB} [Player] Setting up event listeners and quality tracking");
1032
2357
  setupEventListeners();
1033
2358
  const cleanupQuality = setupQualityTracking();
1034
2359
  configureQuality();
2360
+ console.log("\u{1F3A8} [UI] Initializing Shaka UI");
1035
2361
  await initializeUI();
1036
- initializeMux();
1037
- initializeAds();
1038
- initializeChromecast();
2362
+ console.log("\u2705 [UI] UI initialized");
2363
+ if (imaConfig?.adTagUrl && window.google?.ima) {
2364
+ console.log("\u{1F4E2} [Ads] Initializing ads (will load manifest after VAST fetch)");
2365
+ await initializeAds();
2366
+ console.log("\u2705 [Ads] Ads initialized and manifest loaded");
2367
+ }
2368
+ console.log("\u2728 [Player] Initialization complete!");
1039
2369
  } catch (error) {
1040
- console.error("Error during player initialization:", error);
2370
+ console.error("\u274C [Player] Error during initialization:", error);
1041
2371
  handleMuxError(error);
1042
2372
  }
1043
2373
  };
1044
2374
  initialize();
1045
2375
  return () => {
1046
2376
  cleanupEventListeners();
2377
+ cleanupAdEventListeners();
1047
2378
  destroyUI();
1048
2379
  destroyMux();
1049
2380
  destroyPlayer();
1050
2381
  };
1051
- }, [
1052
- src,
1053
- initializePlayer,
1054
- setupEventListeners,
1055
- setupQualityTracking,
1056
- configureQuality,
1057
- initializeUI,
1058
- initializeMux,
1059
- cleanupEventListeners,
1060
- destroyUI,
1061
- destroyMux,
1062
- destroyPlayer,
1063
- handleMuxError,
1064
- playerRef
1065
- ]);
2382
+ }, [managedMode ? hasPlaylist : src, isScriptsLoaded, bfResetKey, managedMode]);
2383
+ useEffect4(() => {
2384
+ const video = videoRef.current;
2385
+ if (!video) return;
2386
+ const onLoadStart = () => {
2387
+ setIsInitialLoading(true);
2388
+ };
2389
+ const onCanPlay = () => {
2390
+ setIsInitialLoading(false);
2391
+ };
2392
+ const onPlaying = () => {
2393
+ setIsInitialLoading(false);
2394
+ };
2395
+ video.addEventListener("loadstart", onLoadStart);
2396
+ video.addEventListener("canplay", onCanPlay);
2397
+ video.addEventListener("playing", onPlaying);
2398
+ return () => {
2399
+ video.removeEventListener("loadstart", onLoadStart);
2400
+ video.removeEventListener("canplay", onCanPlay);
2401
+ video.removeEventListener("playing", onPlaying);
2402
+ };
2403
+ }, []);
1066
2404
  useEffect4(() => {
1067
2405
  const video = videoRef.current;
1068
2406
  if (!video) return;
1069
2407
  video.autoplay = autoPlay;
1070
2408
  video.loop = loop;
1071
- video.muted = muted;
1072
2409
  video.controls = false;
1073
2410
  if (poster) video.poster = poster;
1074
- }, [autoPlay, loop, muted, poster]);
2411
+ }, [autoPlay, loop, muted, poster, imaConfig?.adTagUrl]);
2412
+ useEffect4(() => {
2413
+ const video = videoRef.current;
2414
+ if (!video) return;
2415
+ video.controls = false;
2416
+ video.setAttribute("controls", "false");
2417
+ video.removeAttribute("controls");
2418
+ const observer = new MutationObserver((mutations) => {
2419
+ mutations.forEach((mutation) => {
2420
+ if (mutation.type === "attributes" && mutation.attributeName === "controls") {
2421
+ if (video.hasAttribute("controls")) {
2422
+ video.removeAttribute("controls");
2423
+ video.controls = false;
2424
+ }
2425
+ }
2426
+ });
2427
+ });
2428
+ observer.observe(video, {
2429
+ attributes: true,
2430
+ attributeFilter: ["controls"]
2431
+ });
2432
+ return () => {
2433
+ observer.disconnect();
2434
+ };
2435
+ }, []);
1075
2436
  useImperativeHandle(ref, () => ({
1076
2437
  ...videoRef.current,
1077
2438
  // Custom methods for quality control
@@ -1082,27 +2443,30 @@ var Player = forwardRef(
1082
2443
  skipForward,
1083
2444
  // Mux methods
1084
2445
  updateMuxData,
2446
+ // Live status methods
2447
+ getLiveStatus,
2448
+ seekToLiveEdge,
1085
2449
  // Access to underlying instances
1086
2450
  getPlayer: () => playerRef.current,
1087
2451
  getMuxMonitor: () => null
1088
- }), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData]);
2452
+ }), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData, getLiveStatus, seekToLiveEdge]);
1089
2453
  const isResponsive = !width && !height;
1090
- const containerClasses = twMerge2(containerClassName, "motto-video-container");
2454
+ const containerClasses = twMerge2(containerClassName, "motto-video-container relative bg-[#111111] ");
1091
2455
  const containerStyle = isResponsive ? {
1092
2456
  aspectRatio: aspectRatio.toString()
1093
2457
  } : { width, height };
1094
- const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
2458
+ const videoClasses = isResponsive ? "motto-video-responsive w-full" : "w-full h-full ";
1095
2459
  const videoStyle = isResponsive ? {} : { width, height };
2460
+ const filteredVideoProps = { ...videoProps };
2461
+ delete filteredVideoProps.controls;
1096
2462
  return /* @__PURE__ */ jsxs4(
1097
2463
  "div",
1098
2464
  {
1099
2465
  ref: containerRef,
1100
2466
  className: containerClasses,
1101
2467
  style: containerStyle,
1102
- "data-shaka-player-container": true,
1103
- "data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
1104
2468
  children: [
1105
- /* @__PURE__ */ jsx5(
2469
+ /* @__PURE__ */ jsx7(
1106
2470
  "video",
1107
2471
  {
1108
2472
  ref: videoRef,
@@ -1111,17 +2475,11 @@ var Player = forwardRef(
1111
2475
  height: isResponsive ? void 0 : height,
1112
2476
  style: videoStyle,
1113
2477
  controls: false,
1114
- ...props
2478
+ playsInline: true,
2479
+ ...filteredVideoProps
1115
2480
  }
1116
2481
  ),
1117
- /* @__PURE__ */ jsx5(LiveBadge, { isVisible: isLiveBadgeVisible }),
1118
- imaConfig && /* @__PURE__ */ jsx5(
1119
- "div",
1120
- {
1121
- ref: adContainerRef,
1122
- className: "absolute top-0 left-0 w-full h-full pointer-events-auto"
1123
- }
1124
- )
2482
+ isInitialLoading && /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 flex items-center justify-center z-20 pointer-events-none", children: /* @__PURE__ */ jsx7(Loading, { className: "bg-transparent" }) })
1125
2483
  ]
1126
2484
  }
1127
2485
  );
@@ -1135,11 +2493,11 @@ import { twMerge as twMerge3 } from "tailwind-merge";
1135
2493
  import { useQuery } from "@tanstack/react-query";
1136
2494
 
1137
2495
  // src/api/video.ts
1138
- var fetchVideoData = async (videoId, publicKey, mottoToken) => {
2496
+ var fetchVideoData = async (videoId, publicKey, mottoToken, adsEnabled = false, locale = "en") => {
1139
2497
  const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/GetVideo";
1140
2498
  const url = new URL(endpoint);
1141
2499
  url.searchParams.set("encoding", "json");
1142
- url.searchParams.set("message", JSON.stringify({ videoId }));
2500
+ url.searchParams.set("message", JSON.stringify({ videoId, enable_ads: adsEnabled, locale }));
1143
2501
  const response = await fetch(url, {
1144
2502
  method: "GET",
1145
2503
  headers: {
@@ -1153,14 +2511,14 @@ var fetchVideoData = async (videoId, publicKey, mottoToken) => {
1153
2511
  const data = await response.json();
1154
2512
  return data.video;
1155
2513
  };
1156
- async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0) {
2514
+ async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0, adsEnabled = true, locale = "en") {
1157
2515
  if (!videoIds || videoIds.length === 0) {
1158
2516
  return [];
1159
2517
  }
1160
2518
  const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/BatchGetVideos";
1161
2519
  const url = new URL(endpoint);
1162
2520
  url.searchParams.set("encoding", "json");
1163
- url.searchParams.set("message", JSON.stringify({ videoIds }));
2521
+ url.searchParams.set("message", JSON.stringify({ videoIds, enable_ads: adsEnabled, locale }));
1164
2522
  const response = await fetch(url.toString(), {
1165
2523
  method: "GET",
1166
2524
  headers: {
@@ -1271,7 +2629,7 @@ var getErrorType = (error, video) => {
1271
2629
  };
1272
2630
 
1273
2631
  // src/messages/useMessages.tsx
1274
- import { useState as useState3, useEffect as useEffect5 } from "react";
2632
+ import { useState as useState4, useEffect as useEffect5 } from "react";
1275
2633
 
1276
2634
  // src/messages/en.json
1277
2635
  var en_default = {
@@ -1573,8 +2931,8 @@ var getBrowserLanguage = () => {
1573
2931
  return availableLanguages[language] ? language : "en";
1574
2932
  };
1575
2933
  var useMessages = (locale) => {
1576
- const [language, setLanguage] = useState3("en");
1577
- const [translations, setTranslations] = useState3(availableLanguages.en);
2934
+ const [language, setLanguage] = useState4("en");
2935
+ const [translations, setTranslations] = useState4(availableLanguages.en);
1578
2936
  useEffect5(() => {
1579
2937
  const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
1580
2938
  ;
@@ -1601,11 +2959,10 @@ var useMessages = (locale) => {
1601
2959
  var useMessages_default = useMessages;
1602
2960
 
1603
2961
  // src/Video.tsx
1604
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2962
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1605
2963
  var Video = ({
1606
2964
  videoId,
1607
2965
  publicKey,
1608
- mottoToken,
1609
2966
  videoData: providedVideoData,
1610
2967
  refetchInterval = 0,
1611
2968
  playerName,
@@ -1613,7 +2970,10 @@ var Video = ({
1613
2970
  events,
1614
2971
  children,
1615
2972
  className,
2973
+ auth,
2974
+ settings,
1616
2975
  queryOptions = {},
2976
+ adsEnabled = false,
1617
2977
  ...props
1618
2978
  }) => {
1619
2979
  const {
@@ -1622,8 +2982,8 @@ var Video = ({
1622
2982
  error,
1623
2983
  refetch
1624
2984
  } = useQuery({
1625
- queryKey: ["video", videoId, publicKey, mottoToken],
1626
- queryFn: () => fetchVideoData(videoId, publicKey, mottoToken),
2985
+ queryKey: ["video", videoId, publicKey, auth?.mottoToken, adsEnabled, locale],
2986
+ queryFn: () => fetchVideoData(videoId, publicKey, auth?.mottoToken, adsEnabled, locale),
1627
2987
  enabled: !!videoId && !!publicKey && !providedVideoData,
1628
2988
  refetchInterval: refetchInterval > 0 ? refetchInterval : false,
1629
2989
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -1636,16 +2996,17 @@ var Video = ({
1636
2996
  const video = providedVideoData || data;
1637
2997
  const { t } = useMessages_default(locale);
1638
2998
  const activePlaylist = findHLSPlaylist(video);
1639
- const hlsUrl = activePlaylist?.url;
2999
+ const activePlaylistUrl = activePlaylist?.url ?? activePlaylist?.drm?.widevine?.playlistUrl ?? activePlaylist?.drm?.playready?.playlistUrl ?? activePlaylist?.drm?.fairplay?.playlistUrl;
3000
+ const activePlaylistHasUrl = !!activePlaylistUrl;
1640
3001
  useEffect6(() => {
1641
3002
  if (events?.onVideoData && video) {
1642
3003
  events.onVideoData(video);
1643
3004
  }
1644
3005
  }, [video, events]);
1645
3006
  if (isLoading || !providedVideoData && !video) {
1646
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx6("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx6(Loading, {}) }) });
3007
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx8(Loading, {}) }) });
1647
3008
  }
1648
- if (!isLoading && video && !hlsUrl && events?.onEmptyPlaylists) {
3009
+ if (!isLoading && video && !activePlaylistHasUrl && events?.onEmptyPlaylists) {
1649
3010
  events.onEmptyPlaylists();
1650
3011
  }
1651
3012
  if (error || video?.error) {
@@ -1656,8 +3017,8 @@ var Video = ({
1656
3017
  }
1657
3018
  const title = t(errorKey) || t("DEFAULT_ERROR");
1658
3019
  const description = t(`${errorKey}_DESCRIPTION`) || t("DEFAULT_ERROR_DESCRIPTION");
1659
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full", children: [
1660
- /* @__PURE__ */ jsx6(
3020
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full", children: [
3021
+ /* @__PURE__ */ jsx8(
1661
3022
  ErrorScreen,
1662
3023
  {
1663
3024
  title,
@@ -1667,31 +3028,35 @@ var Video = ({
1667
3028
  children
1668
3029
  ] }) });
1669
3030
  }
1670
- if (!hlsUrl) {
1671
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full bg-[#151515]", children: [
1672
- /* @__PURE__ */ jsx6(Title, { title: video?.name || "" }),
3031
+ if (!activePlaylist || !activePlaylistHasUrl) {
3032
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs5("div", { className: "relative w-full h-full bg-[#151515]", children: [
3033
+ /* @__PURE__ */ jsx8(Title, { title: video?.name || "" }),
1673
3034
  children
1674
3035
  ] }) });
1675
3036
  }
1676
- console.log("hlsUrl", hlsUrl);
1677
- return /* @__PURE__ */ jsx6("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx6("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx6(
3037
+ return /* @__PURE__ */ jsx8("div", { className: twMerge3("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(
1678
3038
  Player,
1679
3039
  {
1680
3040
  ...props,
1681
- src: hlsUrl,
3041
+ src: activePlaylist,
3042
+ managedMode: true,
1682
3043
  className: twMerge3("video-player-container", className),
1683
3044
  events,
3045
+ locale,
1684
3046
  containerClassName: "w-full h-full",
3047
+ publicKey,
3048
+ auth,
3049
+ ...adsEnabled && video?.ad?.adTagUrl ? { imaConfig: { adTagUrl: video?.ad?.adTagUrl } } : {},
1685
3050
  children
1686
3051
  }
1687
3052
  ) }) });
1688
3053
  };
1689
3054
 
1690
3055
  // src/Event.tsx
1691
- import { useCallback as useCallback7, useEffect as useEffect7, useState as useState4 } from "react";
3056
+ import { useCallback as useCallback10, useEffect as useEffect7, useState as useState5 } from "react";
1692
3057
  import { twMerge as twMerge4 } from "tailwind-merge";
1693
3058
  import { useQuery as useQuery2 } from "@tanstack/react-query";
1694
- import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3059
+ import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1695
3060
  var Event = ({
1696
3061
  publicKey,
1697
3062
  eventId,
@@ -1704,6 +3069,7 @@ var Event = ({
1704
3069
  settings,
1705
3070
  auth,
1706
3071
  queryOptions = {},
3072
+ adsEnabled = false,
1707
3073
  ...props
1708
3074
  }) => {
1709
3075
  const {
@@ -1721,16 +3087,16 @@ var Event = ({
1721
3087
  retry: queryOptions.retry ?? 3,
1722
3088
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1723
3089
  });
1724
- const [activePlaylist, setActivePlaylist] = useState4();
1725
- const [activeVideoId, setActiveVideoId] = useState4();
3090
+ const [activePlaylist, setActivePlaylist] = useState5();
3091
+ const [activeVideoId, setActiveVideoId] = useState5();
1726
3092
  const videoIds = eventData?.videoIds ?? [];
1727
3093
  const {
1728
3094
  data: videosData,
1729
3095
  isLoading: videosIsLoading,
1730
3096
  error: videosError
1731
3097
  } = useQuery2({
1732
- queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
1733
- queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
3098
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
3099
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
1734
3100
  enabled: !!publicKey && videoIds.length > 0,
1735
3101
  refetchInterval: activePlaylist === null ? 3e4 : false,
1736
3102
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -1738,7 +3104,7 @@ var Event = ({
1738
3104
  retry: queryOptions.retry ?? 3,
1739
3105
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1740
3106
  });
1741
- const [loadingApisState, setLoadingApisState] = useState4(true);
3107
+ const [loadingApisState, setLoadingApisState] = useState5(true);
1742
3108
  useEffect7(() => {
1743
3109
  if (videosData !== void 0) {
1744
3110
  setLoadingApisState(false);
@@ -1748,9 +3114,11 @@ var Event = ({
1748
3114
  if (videosWithPlaylists.length > 0) {
1749
3115
  let hlsPlaylistFound = false;
1750
3116
  for (const video of videosWithPlaylists) {
1751
- const hlsPlaylist = findHLSPlaylist(video);
1752
- if (hlsPlaylist?.url) {
1753
- setActivePlaylist(hlsPlaylist.url);
3117
+ const activePlaylist2 = findHLSPlaylist(video);
3118
+ const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
3119
+ const activePlaylistHasUrl = !!activePlaylistUrl;
3120
+ if (activePlaylist2 && activePlaylistHasUrl) {
3121
+ setActivePlaylist(activePlaylist2);
1754
3122
  setActiveVideoId(video.id);
1755
3123
  hlsPlaylistFound = true;
1756
3124
  break;
@@ -1784,12 +3152,17 @@ var Event = ({
1784
3152
  }
1785
3153
  }
1786
3154
  }, [activeVideoId, videosData, events]);
1787
- const [error, setError] = useState4(null);
1788
- const [loadingPlaylist, setLoadingPlaylist] = useState4(true);
3155
+ const [error, setError] = useState5(null);
3156
+ const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
1789
3157
  const videosDataError = videosData?.some((video) => !!video.error);
1790
3158
  useEffect7(() => {
1791
- if (eventError || videosError || videosDataError) {
1792
- const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
3159
+ if (isEventLoading || videosIsLoading || loadingApisState) {
3160
+ return;
3161
+ }
3162
+ const hasPlayablePlaylist = Boolean(activePlaylist);
3163
+ if (eventError || videosError || videosDataError && !hasPlayablePlaylist) {
3164
+ const firstVideoError = videosData?.find((video) => !!video.error)?.error;
3165
+ const errorObj = eventError || videosError || firstVideoError && new Error(firstVideoError) || new Error("default");
1793
3166
  setError(errorObj);
1794
3167
  if (events?.onError) {
1795
3168
  events.onError(errorObj);
@@ -1797,7 +3170,17 @@ var Event = ({
1797
3170
  } else {
1798
3171
  setError(null);
1799
3172
  }
1800
- }, [eventError, videosError, videosDataError, videosData, events]);
3173
+ }, [
3174
+ eventError,
3175
+ videosError,
3176
+ videosDataError,
3177
+ videosData,
3178
+ events,
3179
+ activePlaylist,
3180
+ isEventLoading,
3181
+ videosIsLoading,
3182
+ loadingApisState
3183
+ ]);
1801
3184
  useEffect7(() => {
1802
3185
  const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
1803
3186
  const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
@@ -1808,7 +3191,7 @@ var Event = ({
1808
3191
  if (error) {
1809
3192
  const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
1810
3193
  const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
1811
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx7(
3194
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1812
3195
  ErrorScreen,
1813
3196
  {
1814
3197
  title,
@@ -1820,22 +3203,28 @@ var Event = ({
1820
3203
  events.onEmptyPlaylists();
1821
3204
  }
1822
3205
  if (loadingPlaylist) {
1823
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ jsx7(Loading, {}) }) });
3206
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx9(Loading, {}) }) });
1824
3207
  }
1825
3208
  if (activePlaylist && activeVideoId && videosData) {
1826
3209
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
1827
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs6("div", { className: "relative w-full h-full", children: [
1828
- /* @__PURE__ */ jsx7(
3210
+ console.log("activeVideo?.ad?.adTagUrl", activeVideo?.ad?.adTagUrl);
3211
+ return /* @__PURE__ */ jsxs6("div", { className: twMerge4("", className), children: [
3212
+ /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1829
3213
  Player,
1830
3214
  {
1831
3215
  ...props,
1832
3216
  src: activePlaylist,
1833
- className: twMerge4(className, "peer"),
3217
+ managedMode: true,
3218
+ className: twMerge4(className, "peer aspect-video"),
1834
3219
  events,
1835
- containerClassName: "w-full h-full"
3220
+ locale,
3221
+ containerClassName: "w-full h-full",
3222
+ publicKey,
3223
+ auth,
3224
+ ...adsEnabled && activeVideo ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
1836
3225
  }
1837
- ),
1838
- !hideTitle && eventData && /* @__PURE__ */ jsx7(
3226
+ ) }),
3227
+ !hideTitle && eventData && /* @__PURE__ */ jsx9(
1839
3228
  TitleAndDescription,
1840
3229
  {
1841
3230
  title: eventData.title,
@@ -1844,10 +3233,10 @@ var Event = ({
1844
3233
  locale
1845
3234
  }
1846
3235
  )
1847
- ] }) });
3236
+ ] });
1848
3237
  }
1849
3238
  if (eventData) {
1850
- return /* @__PURE__ */ jsx7("div", { className: twMerge4("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx7(
3239
+ return /* @__PURE__ */ jsx9("div", { className: twMerge4("", className), children: /* @__PURE__ */ jsx9("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx9(
1851
3240
  PreEvent,
1852
3241
  {
1853
3242
  event: eventData,
@@ -1869,7 +3258,7 @@ function PreEvent({
1869
3258
  }) {
1870
3259
  const date = new Date(event.startTime);
1871
3260
  const now = /* @__PURE__ */ new Date();
1872
- const [remainingTime, setRemainingTime] = useState4(
3261
+ const [remainingTime, setRemainingTime] = useState5(
1873
3262
  date.getTime() - now.getTime()
1874
3263
  );
1875
3264
  const shouldBeStarted = remainingTime < 0;
@@ -1884,29 +3273,28 @@ function PreEvent({
1884
3273
  }, 1e3);
1885
3274
  return () => clearInterval(interval);
1886
3275
  }, [date, remainingTime]);
1887
- const renderCountdown = useCallback7(() => {
3276
+ const renderCountdown = useCallback10(() => {
1888
3277
  if (shouldBeStarted) {
1889
- return /* @__PURE__ */ jsx7("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
3278
+ return /* @__PURE__ */ jsx9("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
1890
3279
  }
1891
3280
  const seconds = Math.floor(remainingTime / 1e3) % 60;
1892
3281
  const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
1893
3282
  const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
1894
3283
  const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
1895
- return /* @__PURE__ */ jsxs6("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
3284
+ return /* @__PURE__ */ jsxs6("div", { className: "grid grid-flow-col gap-1 md:gap-5 text-center auto-cols-max", children: [
1896
3285
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1897
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3286
+ /* @__PURE__ */ jsx9("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1898
3287
  "span",
1899
3288
  {
1900
- style: { "--value": days },
1901
3289
  "aria-live": "polite",
1902
3290
  "aria-label": days.toString(),
1903
- children: days?.toString()?.padStart(2, "0")
3291
+ children: days.toString()
1904
3292
  }
1905
3293
  ) }),
1906
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
3294
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
1907
3295
  ] }),
1908
3296
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1909
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3297
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1910
3298
  "span",
1911
3299
  {
1912
3300
  style: { "--value": hours },
@@ -1915,10 +3303,10 @@ function PreEvent({
1915
3303
  children: hours?.toString()?.padStart(2, "0")
1916
3304
  }
1917
3305
  ) }),
1918
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
3306
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
1919
3307
  ] }),
1920
3308
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1921
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3309
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1922
3310
  "span",
1923
3311
  {
1924
3312
  style: { "--value": minutes },
@@ -1927,10 +3315,10 @@ function PreEvent({
1927
3315
  children: minutes?.toString()?.padStart(2, "0")
1928
3316
  }
1929
3317
  ) }),
1930
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
3318
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
1931
3319
  ] }),
1932
3320
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
1933
- /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
3321
+ /* @__PURE__ */ jsx9("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx9(
1934
3322
  "span",
1935
3323
  {
1936
3324
  style: { "--value": seconds },
@@ -1939,12 +3327,12 @@ function PreEvent({
1939
3327
  children: seconds?.toString()?.padStart(2, "0")
1940
3328
  }
1941
3329
  ) }),
1942
- /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
3330
+ /* @__PURE__ */ jsx9("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
1943
3331
  ] })
1944
3332
  ] });
1945
3333
  }, [remainingTime, shouldBeStarted, t]);
1946
- return /* @__PURE__ */ jsx7(Fragment, { children: event?.posterUrl ? /* @__PURE__ */ jsxs6(Fragment, { children: [
1947
- /* @__PURE__ */ jsx7(
3334
+ return /* @__PURE__ */ jsx9(Fragment, { children: event?.posterUrl ? /* @__PURE__ */ jsxs6(Fragment, { children: [
3335
+ /* @__PURE__ */ jsx9(
1948
3336
  "div",
1949
3337
  {
1950
3338
  className: "relative overflow-hidden bg-base-200 aspect-video text-base-content w-full h-full flex justify-center items-center flex-col bg-no-repeat bg-cover md:rounded-2xl",
@@ -1953,10 +3341,10 @@ function PreEvent({
1953
3341
  backgroundRepeat: "no-repeat",
1954
3342
  backgroundSize: "cover"
1955
3343
  },
1956
- children: /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
3344
+ children: /* @__PURE__ */ jsx9("div", { className: "relative z-10", children: renderCountdown() })
1957
3345
  }
1958
3346
  ),
1959
- !hideTitle && /* @__PURE__ */ jsx7(
3347
+ !hideTitle && /* @__PURE__ */ jsx9(
1960
3348
  TitleAndDescription,
1961
3349
  {
1962
3350
  title: event.title,
@@ -1966,17 +3354,17 @@ function PreEvent({
1966
3354
  }
1967
3355
  )
1968
3356
  ] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
1969
- /* @__PURE__ */ jsx7(
3357
+ /* @__PURE__ */ jsx9(
1970
3358
  "div",
1971
3359
  {
1972
3360
  className: "relative overflow-hidden md:rounded-2xl bg-base-200 aspect-video text-base-content flex flex-col justify-center items-center w-full h-full bg-cover bg-center bg-no-repeat",
1973
3361
  style: {
1974
3362
  backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
1975
3363
  },
1976
- children: /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
3364
+ children: /* @__PURE__ */ jsx9("div", { className: "relative z-10", children: renderCountdown() })
1977
3365
  }
1978
3366
  ),
1979
- !hideTitle && /* @__PURE__ */ jsx7(
3367
+ !hideTitle && /* @__PURE__ */ jsx9(
1980
3368
  TitleAndDescription,
1981
3369
  {
1982
3370
  title: event.title,
@@ -1995,8 +3383,8 @@ var TitleAndDescription = ({
1995
3383
  className
1996
3384
  }) => {
1997
3385
  return /* @__PURE__ */ jsxs6("div", { className: twMerge4("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
1998
- /* @__PURE__ */ jsx7("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
1999
- startTime ? /* @__PURE__ */ jsxs6("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
3386
+ /* @__PURE__ */ jsx9("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
3387
+ startTime ? /* @__PURE__ */ jsxs6("div", { className: "text-xs md:text-base text-base-content/70 m-event-start-time", children: [
2000
3388
  new Date(startTime || "").toLocaleDateString(locale || "default", {
2001
3389
  month: "long",
2002
3390
  year: "numeric",
@@ -2009,15 +3397,15 @@ var TitleAndDescription = ({
2009
3397
  minute: "2-digit"
2010
3398
  })
2011
3399
  ] }) : null,
2012
- description && /* @__PURE__ */ jsx7("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
3400
+ description && /* @__PURE__ */ jsx9("div", { className: "text-xs md:text-xs text-base-content/60 uppercase", children: description })
2013
3401
  ] });
2014
3402
  };
2015
3403
 
2016
3404
  // src/CreativeWork.tsx
2017
- import { useEffect as useEffect8, useState as useState5 } from "react";
3405
+ import { useEffect as useEffect8, useState as useState6 } from "react";
2018
3406
  import { twMerge as twMerge5 } from "tailwind-merge";
2019
3407
  import { useQuery as useQuery3 } from "@tanstack/react-query";
2020
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3408
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2021
3409
  var CreativeWork = ({
2022
3410
  publicKey,
2023
3411
  creativeWorkId,
@@ -2030,6 +3418,7 @@ var CreativeWork = ({
2030
3418
  settings,
2031
3419
  auth,
2032
3420
  queryOptions = {},
3421
+ adsEnabled = false,
2033
3422
  ...props
2034
3423
  }) => {
2035
3424
  const {
@@ -2047,17 +3436,17 @@ var CreativeWork = ({
2047
3436
  retry: queryOptions.retry ?? 3,
2048
3437
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2049
3438
  });
2050
- const [activePlaylist, setActivePlaylist] = useState5();
2051
- const [activeVideoId, setActiveVideoId] = useState5();
2052
- const [showCountDown, setShowCountDown] = useState5(false);
3439
+ const [activePlaylist, setActivePlaylist] = useState6();
3440
+ const [activeVideoId, setActiveVideoId] = useState6();
3441
+ const [showCountDown, setShowCountDown] = useState6(false);
2053
3442
  const videoIds = creativeWorkData?.videoIds ?? [];
2054
3443
  const {
2055
3444
  data: videosData,
2056
3445
  isLoading: videosIsLoading,
2057
3446
  error: videosError
2058
3447
  } = useQuery3({
2059
- queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
2060
- queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
3448
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
3449
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
2061
3450
  enabled: !!publicKey && videoIds.length > 0,
2062
3451
  refetchInterval: activePlaylist === null ? 3e4 : false,
2063
3452
  staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
@@ -2065,7 +3454,7 @@ var CreativeWork = ({
2065
3454
  retry: queryOptions.retry ?? 3,
2066
3455
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2067
3456
  });
2068
- const [loadingApisState, setLoadingApisState] = useState5(true);
3457
+ const [loadingApisState, setLoadingApisState] = useState6(true);
2069
3458
  useEffect8(() => {
2070
3459
  if (videosData !== void 0) {
2071
3460
  setLoadingApisState(false);
@@ -2075,9 +3464,11 @@ var CreativeWork = ({
2075
3464
  if (videosWithPlaylists.length > 0) {
2076
3465
  let hlsPlaylistFound = false;
2077
3466
  for (const video of videosWithPlaylists) {
2078
- const hlsPlaylist = findHLSPlaylist(video);
2079
- if (hlsPlaylist?.url) {
2080
- setActivePlaylist(hlsPlaylist.url);
3467
+ const activePlaylist2 = findHLSPlaylist(video);
3468
+ const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
3469
+ const activePlaylistHasUrl = !!activePlaylistUrl;
3470
+ if (activePlaylist2 && activePlaylistHasUrl) {
3471
+ setActivePlaylist(activePlaylist2);
2081
3472
  setActiveVideoId(video.id);
2082
3473
  hlsPlaylistFound = true;
2083
3474
  break;
@@ -2114,7 +3505,7 @@ var CreativeWork = ({
2114
3505
  }
2115
3506
  }
2116
3507
  }, [activeVideoId, videosData, events]);
2117
- const [error, setError] = useState5(null);
3508
+ const [error, setError] = useState6(null);
2118
3509
  const videosDataError = videosData?.some((video) => !!video.error);
2119
3510
  useEffect8(() => {
2120
3511
  if (creativeWorkError || videosError || videosDataError) {
@@ -2130,7 +3521,7 @@ var CreativeWork = ({
2130
3521
  if (error) {
2131
3522
  const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
2132
3523
  const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
2133
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(
3524
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx10(
2134
3525
  ErrorScreen,
2135
3526
  {
2136
3527
  title,
@@ -2138,7 +3529,7 @@ var CreativeWork = ({
2138
3529
  }
2139
3530
  ) }) });
2140
3531
  }
2141
- const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
3532
+ const [loadingPlaylist, setLoadingPlaylist] = useState6(true);
2142
3533
  useEffect8(() => {
2143
3534
  const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
2144
3535
  const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
@@ -2160,10 +3551,10 @@ var CreativeWork = ({
2160
3551
  events
2161
3552
  ]);
2162
3553
  if (isCreativeWorkLoading || videosIsLoading || loadingApisState) {
2163
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full", children: /* @__PURE__ */ jsx8(Loading, {}) }) });
3554
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx10(Loading, {}) }) });
2164
3555
  }
2165
3556
  if (showCountDown && creativeWorkData) {
2166
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsx8("div", { className: "relative w-full h-full bg-base-200 text-base-content flex justify-center items-center flex-col", children: /* @__PURE__ */ jsx8(
3557
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full h-full bg-base-200 text-base-content flex justify-center items-center flex-col", children: /* @__PURE__ */ jsx10(
2167
3558
  PreCreativeWork,
2168
3559
  {
2169
3560
  creativeWork: creativeWorkData,
@@ -2176,20 +3567,25 @@ var CreativeWork = ({
2176
3567
  }
2177
3568
  if (activeVideoId && activePlaylist && !loadingPlaylist) {
2178
3569
  const activeVideo = videosData?.find((video) => video.id === activeVideoId);
2179
- return /* @__PURE__ */ jsx8("div", { className: twMerge5("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ jsxs7("div", { className: "relative w-full h-full", children: [
2180
- /* @__PURE__ */ jsx8(
3570
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsxs7("div", { className: "relative w-full h-full", children: [
3571
+ /* @__PURE__ */ jsx10(
2181
3572
  Player,
2182
3573
  {
2183
3574
  ...props,
2184
- className: twMerge5(className, "peer"),
3575
+ className: twMerge5(className, "peer aspect-video"),
3576
+ managedMode: true,
2185
3577
  events: {
2186
3578
  ...events
2187
3579
  },
2188
3580
  src: activePlaylist,
2189
- containerClassName: "w-full h-full"
3581
+ locale,
3582
+ containerClassName: "w-full h-full",
3583
+ publicKey,
3584
+ auth,
3585
+ ...adsEnabled && activeVideo?.ad?.adTagUrl ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
2190
3586
  }
2191
3587
  ),
2192
- !hideTitle && /* @__PURE__ */ jsx8(
3588
+ !hideTitle && /* @__PURE__ */ jsx10(
2193
3589
  TitleAndDescription2,
2194
3590
  {
2195
3591
  title: creativeWorkData?.title || "",
@@ -2202,7 +3598,7 @@ var CreativeWork = ({
2202
3598
  ] }) });
2203
3599
  }
2204
3600
  if (loadingPlaylist) {
2205
- return /* @__PURE__ */ jsx8(Loading, {});
3601
+ return /* @__PURE__ */ jsx10("div", { className: twMerge5("", className), children: /* @__PURE__ */ jsx10("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ jsx10(Loading, {}) }) });
2206
3602
  }
2207
3603
  return null;
2208
3604
  };
@@ -2215,7 +3611,7 @@ function PreCreativeWork({
2215
3611
  }) {
2216
3612
  const date = new Date(creativeWork.releaseTime);
2217
3613
  const now = /* @__PURE__ */ new Date();
2218
- const [remainingTime, setRemainingTime] = useState5(
3614
+ const [remainingTime, setRemainingTime] = useState6(
2219
3615
  date.getTime() - now.getTime()
2220
3616
  );
2221
3617
  const shouldBeStarted = remainingTime < 0;
@@ -2234,27 +3630,26 @@ function PreCreativeWork({
2234
3630
  }, [date, remainingTime]);
2235
3631
  const renderCountdown = () => {
2236
3632
  if (shouldBeStarted) {
2237
- return /* @__PURE__ */ jsx8("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
3633
+ return /* @__PURE__ */ jsx10("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
2238
3634
  }
2239
3635
  const seconds = Math.floor(remainingTime / 1e3) % 60;
2240
3636
  const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
2241
3637
  const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
2242
3638
  const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
2243
- return /* @__PURE__ */ jsxs7("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
3639
+ return /* @__PURE__ */ jsxs7("div", { className: "grid grid-flow-col md:gap-5 gap-1 text-center auto-cols-max", children: [
2244
3640
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2245
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3641
+ /* @__PURE__ */ jsx10("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2246
3642
  "span",
2247
3643
  {
2248
- style: { "--value": days },
2249
3644
  "aria-live": "polite",
2250
3645
  "aria-label": days.toString(),
2251
- children: days?.toString()?.padStart(2, "0")
3646
+ children: days.toString()
2252
3647
  }
2253
3648
  ) }),
2254
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
3649
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
2255
3650
  ] }),
2256
3651
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2257
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3652
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2258
3653
  "span",
2259
3654
  {
2260
3655
  style: { "--value": hours },
@@ -2263,10 +3658,10 @@ function PreCreativeWork({
2263
3658
  children: hours?.toString()?.padStart(2, "0")
2264
3659
  }
2265
3660
  ) }),
2266
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
3661
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
2267
3662
  ] }),
2268
3663
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2269
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3664
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2270
3665
  "span",
2271
3666
  {
2272
3667
  style: { "--value": minutes },
@@ -2275,10 +3670,10 @@ function PreCreativeWork({
2275
3670
  children: minutes?.toString()?.padStart(2, "0")
2276
3671
  }
2277
3672
  ) }),
2278
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
3673
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
2279
3674
  ] }),
2280
3675
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2281
- /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
3676
+ /* @__PURE__ */ jsx10("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ jsx10(
2282
3677
  "span",
2283
3678
  {
2284
3679
  style: { "--value": seconds },
@@ -2287,7 +3682,7 @@ function PreCreativeWork({
2287
3682
  children: seconds?.toString()?.padStart(2, "0")
2288
3683
  }
2289
3684
  ) }),
2290
- /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
3685
+ /* @__PURE__ */ jsx10("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
2291
3686
  ] })
2292
3687
  ] });
2293
3688
  };
@@ -2300,12 +3695,12 @@ function PreCreativeWork({
2300
3695
  backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
2301
3696
  },
2302
3697
  children: [
2303
- backgroundImageUrl && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
2304
- /* @__PURE__ */ jsx8("div", { className: "relative z-10", children: renderCountdown() })
3698
+ backgroundImageUrl && /* @__PURE__ */ jsx10("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
3699
+ /* @__PURE__ */ jsx10("div", { className: "relative z-10", children: renderCountdown() })
2305
3700
  ]
2306
3701
  }
2307
3702
  ),
2308
- !hideTitle && /* @__PURE__ */ jsx8(
3703
+ !hideTitle && /* @__PURE__ */ jsx10(
2309
3704
  TitleAndDescription2,
2310
3705
  {
2311
3706
  title: creativeWork.title,
@@ -2324,7 +3719,7 @@ var TitleAndDescription2 = ({
2324
3719
  className
2325
3720
  }) => {
2326
3721
  return /* @__PURE__ */ jsxs7("div", { className: twMerge5("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
2327
- /* @__PURE__ */ jsx8("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
3722
+ /* @__PURE__ */ jsx10("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
2328
3723
  releaseTime ? /* @__PURE__ */ jsxs7("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
2329
3724
  new Date(releaseTime || "").toLocaleDateString(locale || "default", {
2330
3725
  month: "long",
@@ -2338,13 +3733,13 @@ var TitleAndDescription2 = ({
2338
3733
  minute: "2-digit"
2339
3734
  })
2340
3735
  ] }) : null,
2341
- description && /* @__PURE__ */ jsx8("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
3736
+ description && /* @__PURE__ */ jsx10("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
2342
3737
  ] });
2343
3738
  };
2344
3739
 
2345
3740
  // src/QueryProvider.tsx
2346
3741
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2347
- import { jsx as jsx9 } from "react/jsx-runtime";
3742
+ import { jsx as jsx11 } from "react/jsx-runtime";
2348
3743
  var queryClient = new QueryClient({
2349
3744
  defaultOptions: {
2350
3745
  queries: {
@@ -2358,13 +3753,16 @@ var queryClient = new QueryClient({
2358
3753
  }
2359
3754
  });
2360
3755
  var QueryProvider = ({ children }) => {
2361
- return /* @__PURE__ */ jsx9(QueryClientProvider, { client: queryClient, children });
3756
+ return /* @__PURE__ */ jsx11(QueryClientProvider, { client: queryClient, children });
2362
3757
  };
2363
3758
  export {
3759
+ BigPlayIcon,
2364
3760
  CreativeWork,
2365
3761
  Event,
2366
3762
  Player,
2367
3763
  QueryProvider,
3764
+ SkipBackIcon,
3765
+ SkipForwardIcon,
2368
3766
  Video,
2369
3767
  queryClient
2370
3768
  };