@mottosports/motto-video-player 1.0.0

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 ADDED
@@ -0,0 +1,2590 @@
1
+ "use client";
2
+
3
+ // #style-inject:#style-inject
4
+ function styleInject(css, { insertAt } = {}) {
5
+ if (!css || typeof document === "undefined") return;
6
+ const head = document.head || document.getElementsByTagName("head")[0];
7
+ const style = document.createElement("style");
8
+ style.type = "text/css";
9
+ if (insertAt === "top") {
10
+ if (head.firstChild) {
11
+ head.insertBefore(style, head.firstChild);
12
+ } else {
13
+ head.appendChild(style);
14
+ }
15
+ } else {
16
+ head.appendChild(style);
17
+ }
18
+ if (style.styleSheet) {
19
+ style.styleSheet.cssText = css;
20
+ } else {
21
+ style.appendChild(document.createTextNode(css));
22
+ }
23
+ }
24
+
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 .shaka-controls-container {\n z-index: 90 !important;\n height: 100px !important;\n bottom: 0 !important;\n top: unset !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@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');
27
+
28
+ // src/Player.tsx
29
+ import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle } from "react";
30
+ import shaka2 from "shaka-player/dist/shaka-player.ui";
31
+
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 = ({
36
+ src,
37
+ shakaConfig,
38
+ drmConfig,
39
+ onError,
40
+ onPlayerReady
41
+ }) => {
42
+ const playerRef = useRef(null);
43
+ const initializePlayer = useCallback(async (video) => {
44
+ try {
45
+ polyfill.installAll();
46
+ if (!ShakaPlayer.isBrowserSupported()) {
47
+ throw new Error("Browser not supported by Shaka Player");
48
+ }
49
+ const player = new ShakaPlayer();
50
+ playerRef.current = player;
51
+ await player.attach(video);
52
+ if (shakaConfig) {
53
+ player.configure(shakaConfig);
54
+ }
55
+ if (drmConfig) {
56
+ if (drmConfig.clearKeys) {
57
+ player.configure({ "drm.clearKeys": drmConfig.clearKeys });
58
+ }
59
+ if (drmConfig.servers) {
60
+ player.configure({ "drm.servers": drmConfig.servers });
61
+ }
62
+ }
63
+ player.addEventListener("error", (event) => {
64
+ const error = event.detail;
65
+ console.error("Shaka Player Error:", error);
66
+ onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
67
+ });
68
+ await player.load(src);
69
+ onPlayerReady?.(player);
70
+ return player;
71
+ } catch (error) {
72
+ console.error("Error initializing Shaka Player:", error);
73
+ onError?.(error);
74
+ throw error;
75
+ }
76
+ }, [shakaConfig, drmConfig, src, onError, onPlayerReady]);
77
+ const destroyPlayer = useCallback(async () => {
78
+ if (playerRef.current) {
79
+ try {
80
+ await playerRef.current.destroy();
81
+ } catch (error) {
82
+ console.warn("Error destroying Shaka Player:", error);
83
+ } finally {
84
+ playerRef.current = null;
85
+ }
86
+ }
87
+ }, []);
88
+ return {
89
+ playerRef,
90
+ initializePlayer,
91
+ destroyPlayer
92
+ };
93
+ };
94
+
95
+ // src/hooks/useQualityControl.ts
96
+ import { useCallback as useCallback2 } from "react";
97
+ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
98
+ const getAvailableQualities = useCallback2(() => {
99
+ if (!playerRef.current) return [];
100
+ const tracks = playerRef.current.getVariantTracks();
101
+ const qualities = tracks.filter(
102
+ (track, index, self) => index === self.findIndex((t) => t.height === track.height)
103
+ ).map((track) => ({
104
+ height: track.height || 0,
105
+ bandwidth: track.bandwidth || 0,
106
+ label: `${track.height}p`
107
+ })).sort((a, b) => b.height - a.height);
108
+ return qualities;
109
+ }, [playerRef]);
110
+ const setQuality = useCallback2((height) => {
111
+ if (!playerRef.current) return;
112
+ if (height === 0) {
113
+ playerRef.current.configure({
114
+ abr: { enabled: true }
115
+ });
116
+ } else {
117
+ playerRef.current.configure({
118
+ abr: { enabled: false }
119
+ });
120
+ const tracks = playerRef.current.getVariantTracks();
121
+ const targetTrack = tracks.find((track) => track.height === height);
122
+ if (targetTrack) {
123
+ playerRef.current.selectVariantTrack(
124
+ targetTrack,
125
+ /* clearBuffer= */
126
+ true
127
+ );
128
+ }
129
+ }
130
+ }, [playerRef]);
131
+ const setupQualityTracking = useCallback2(() => {
132
+ if (!playerRef.current || !onQualityChange) return;
133
+ const handleQualityChange = () => {
134
+ const activeTrack = playerRef.current.getVariantTracks().find((track) => track.active);
135
+ if (activeTrack) {
136
+ onQualityChange({
137
+ height: activeTrack.height || 0,
138
+ bandwidth: activeTrack.bandwidth || 0
139
+ });
140
+ }
141
+ };
142
+ playerRef.current.addEventListener("variantchanged", handleQualityChange);
143
+ return () => {
144
+ playerRef.current?.removeEventListener("variantchanged", handleQualityChange);
145
+ };
146
+ }, [playerRef, onQualityChange]);
147
+ const configureQuality = useCallback2(() => {
148
+ if (!playerRef.current || !qualityConfig) return;
149
+ if (qualityConfig.enableAdaptation !== void 0) {
150
+ playerRef.current.configure({
151
+ abr: { enabled: qualityConfig.enableAdaptation }
152
+ });
153
+ }
154
+ if (qualityConfig.selectedQuality !== void 0) {
155
+ setQuality(qualityConfig.selectedQuality);
156
+ }
157
+ }, [playerRef, qualityConfig, setQuality]);
158
+ return {
159
+ getAvailableQualities,
160
+ setQuality,
161
+ setupQualityTracking,
162
+ configureQuality
163
+ };
164
+ };
165
+
166
+ // src/hooks/useSkipControls.ts
167
+ import { useCallback as useCallback3 } from "react";
168
+ var useSkipControls = (videoRef, onSkipBack, onSkipForward) => {
169
+ const skipDuration = 15;
170
+ const skipBack = useCallback3(() => {
171
+ const video = videoRef.current;
172
+ if (!video) return;
173
+ const newTime = Math.max(0, video.currentTime - skipDuration);
174
+ video.currentTime = newTime;
175
+ onSkipBack?.(newTime);
176
+ }, [videoRef, onSkipBack]);
177
+ const skipForward = useCallback3(() => {
178
+ const video = videoRef.current;
179
+ if (!video) return;
180
+ const newTime = Math.min(video.duration || 0, video.currentTime + skipDuration);
181
+ video.currentTime = newTime;
182
+ onSkipForward?.(newTime);
183
+ }, [videoRef, onSkipForward]);
184
+ const shouldShowSkipControls = useCallback3(() => {
185
+ return true;
186
+ }, []);
187
+ return {
188
+ skipBack,
189
+ skipForward,
190
+ skipDuration,
191
+ shouldShowSkipControls
192
+ };
193
+ };
194
+
195
+ // src/hooks/useMuxAnalytics.ts
196
+ 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";
199
+ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
200
+ const shakaPlayerMuxRef = useRef3(null);
201
+ const initializeMux = useCallback4(() => {
202
+ if (!muxConfig || !playerRef.current) return;
203
+ try {
204
+ const playerInitTime = initShakaPlayerMux.utils.now();
205
+ const muxOptions = {
206
+ debug: muxConfig.debug || false,
207
+ disableCookies: muxConfig.disableCookies || false,
208
+ respectDoNotTrack: muxConfig.respectDoNotTrack || false,
209
+ automaticErrorTracking: muxConfig.automaticErrorTracking !== false,
210
+ ...muxConfig.beaconCollectionDomain && { beaconCollectionDomain: muxConfig.beaconCollectionDomain },
211
+ ...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
212
+ data: {
213
+ env_key: muxConfig.envKey,
214
+ player_name: "Motto Video Player",
215
+ player_version: "1.0.0",
216
+ player_init_time: playerInitTime,
217
+ ...muxConfig.metadata
218
+ }
219
+ };
220
+ shakaPlayerMuxRef.current = initShakaPlayerMux(playerRef.current, muxOptions, shaka);
221
+ onMuxReady?.();
222
+ } catch (error) {
223
+ console.error("Failed to initialize Mux Analytics:", error);
224
+ }
225
+ }, [muxConfig, onMuxReady, playerRef]);
226
+ const updateMuxData = useCallback4((data) => {
227
+ if (playerRef.current?.mux?.updateData) {
228
+ try {
229
+ playerRef.current.mux.updateData(data);
230
+ onMuxDataUpdate?.(data);
231
+ } catch (error) {
232
+ console.error("Failed to update Mux data:", error);
233
+ }
234
+ }
235
+ }, [onMuxDataUpdate, playerRef]);
236
+ const handleMuxError = useCallback4((error) => {
237
+ if (shakaPlayerMuxRef.current?.loadErrorHandler) {
238
+ shakaPlayerMuxRef.current.loadErrorHandler(error);
239
+ }
240
+ }, []);
241
+ const destroyMux = useCallback4(() => {
242
+ if (playerRef.current?.mux?.destroy) {
243
+ try {
244
+ playerRef.current.mux.destroy();
245
+ } catch (error) {
246
+ console.error("Error destroying Mux:", error);
247
+ }
248
+ }
249
+ if (shakaPlayerMuxRef.current) {
250
+ shakaPlayerMuxRef.current = null;
251
+ }
252
+ }, [playerRef]);
253
+ return {
254
+ initializeMux,
255
+ updateMuxData,
256
+ handleMuxError,
257
+ destroyMux,
258
+ shakaPlayerMuxRef
259
+ };
260
+ };
261
+
262
+ // src/hooks/useShakaUI.ts
263
+ import { useCallback as useCallback5, useRef as useRef4 } from "react";
264
+ import { ui as ShakaUI } from "shaka-player/dist/shaka-player.ui";
265
+ var SkipBackButton = class {
266
+ constructor(parent, controls, onSkipBack) {
267
+ this.parent = parent;
268
+ this.controls = controls;
269
+ this.eventManager = { listen: (element, event, handler) => {
270
+ element.addEventListener(event, handler);
271
+ } };
272
+ this.button_ = document.createElement("button");
273
+ 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
+ `;
282
+ this.button_.title = "Skip back 15 seconds";
283
+ this.button_.setAttribute("aria-label", "Skip back 15 seconds");
284
+ this.parent.appendChild(this.button_);
285
+ this.eventManager.listen(this.button_, "click", () => {
286
+ const video = this.controls.getVideo();
287
+ if (video) {
288
+ const newTime = Math.max(0, video.currentTime - 15);
289
+ video.currentTime = newTime;
290
+ onSkipBack?.(newTime);
291
+ }
292
+ });
293
+ }
294
+ };
295
+ var SkipForwardButton = class {
296
+ constructor(parent, controls, onSkipForward) {
297
+ this.parent = parent;
298
+ this.controls = controls;
299
+ this.eventManager = { listen: (element, event, handler) => {
300
+ element.addEventListener(event, handler);
301
+ } };
302
+ this.button_ = document.createElement("button");
303
+ 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
+ `;
312
+ this.button_.title = "Skip forward 15 seconds";
313
+ this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
314
+ this.parent.appendChild(this.button_);
315
+ this.eventManager.listen(this.button_, "click", () => {
316
+ const video = this.controls.getVideo();
317
+ if (video) {
318
+ const newTime = Math.min(video.duration || 0, video.currentTime + 15);
319
+ video.currentTime = newTime;
320
+ onSkipForward?.(newTime);
321
+ }
322
+ });
323
+ }
324
+ };
325
+ var SkipBackButtonFactory = class {
326
+ constructor(onSkipBack) {
327
+ this.onSkipBack = onSkipBack;
328
+ }
329
+ create(rootElement, controls) {
330
+ return new SkipBackButton(rootElement, controls, this.onSkipBack);
331
+ }
332
+ };
333
+ 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;
516
+ this.onSkipForward = onSkipForward;
517
+ }
518
+ create(rootElement, controls) {
519
+ return new MobileControlsContainer(rootElement, controls, this.onSkipBack, this.onSkipForward);
520
+ }
521
+ };
522
+ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
523
+ const uiRef = useRef4(null);
524
+ const registeredElements = useRef4(/* @__PURE__ */ new Set());
525
+ const initializeUI = useCallback5(async () => {
526
+ if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
527
+ return null;
528
+ }
529
+ const isMobile = window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
530
+ if (!registeredElements.current.has("skip_back_button")) {
531
+ ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack));
532
+ registeredElements.current.add("skip_back_button");
533
+ }
534
+ if (!registeredElements.current.has("skip_forward_button")) {
535
+ ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward));
536
+ registeredElements.current.add("skip_forward_button");
537
+ }
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
+ const ui = new ShakaUI.Overlay(playerRef.current, containerRef.current, videoRef.current);
545
+ 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",
556
+ "mute",
557
+ "volume",
558
+ "time_and_duration",
559
+ "spacer",
560
+ "fullscreen",
561
+ "overflow_menu"
562
+ ];
563
+ const uiConfig = {
564
+ seekBarColors: {
565
+ base: seekbarColors?.base || "rgba(255, 255, 255, 0.3)",
566
+ // Unbuffered track
567
+ buffered: seekbarColors?.buffered || "rgba(255, 255, 255, 0.5)",
568
+ // Buffered but not played
569
+ played: seekbarColors?.played || "#ffffff"
570
+ // Progress/played portion (white)
571
+ },
572
+ controlPanelElements,
573
+ ...chromecastConfig?.receiverApplicationId && {
574
+ "castReceiverAppId": chromecastConfig.receiverApplicationId,
575
+ "castAndroidReceiverCompatible": false
576
+ }
577
+ };
578
+ if (chromecastConfig?.receiverApplicationId) {
579
+ uiConfig.castReceiverAppId = chromecastConfig.receiverApplicationId;
580
+ uiConfig.castAndroidReceiverCompatible = false;
581
+ }
582
+ ui.configure(uiConfig);
583
+ 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);
589
+ }
590
+ }, 500);
591
+ }
592
+ return ui;
593
+ }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward]);
594
+ const destroyUI = useCallback5(() => {
595
+ if (uiRef.current) {
596
+ try {
597
+ uiRef.current.destroy();
598
+ } catch (error) {
599
+ console.error("Error destroying UI:", error);
600
+ }
601
+ uiRef.current = null;
602
+ }
603
+ }, []);
604
+ return {
605
+ uiRef,
606
+ initializeUI,
607
+ destroyUI
608
+ };
609
+ };
610
+
611
+ // src/hooks/useEventHandlers.ts
612
+ import { useCallback as useCallback6 } from "react";
613
+ var useEventHandlers = (videoRef, handlers) => {
614
+ const setupEventListeners = useCallback6(() => {
615
+ const video = videoRef.current;
616
+ if (!video) return;
617
+ const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
618
+ if (onPlay) video.addEventListener("play", onPlay);
619
+ if (onPause) video.addEventListener("pause", onPause);
620
+ if (onEnded) video.addEventListener("ended", onEnded);
621
+ if (onLoadStart) video.addEventListener("loadstart", onLoadStart);
622
+ if (onCanPlay) video.addEventListener("canplay", onCanPlay);
623
+ }, [videoRef, handlers]);
624
+ const cleanupEventListeners = useCallback6(() => {
625
+ const video = videoRef.current;
626
+ if (!video) return;
627
+ const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
628
+ if (onPlay) video.removeEventListener("play", onPlay);
629
+ if (onPause) video.removeEventListener("pause", onPause);
630
+ if (onEnded) video.removeEventListener("ended", onEnded);
631
+ if (onLoadStart) video.removeEventListener("loadstart", onLoadStart);
632
+ if (onCanPlay) video.removeEventListener("canplay", onCanPlay);
633
+ }, [videoRef, handlers]);
634
+ return {
635
+ setupEventListeners,
636
+ cleanupEventListeners
637
+ };
638
+ };
639
+
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;
650
+ }
651
+ try {
652
+ const player = playerRef.current;
653
+ if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
654
+ return;
655
+ }
656
+ const manifest = player.getManifest();
657
+ if (!manifest) {
658
+ return;
659
+ }
660
+ const timeline = player.getPresentationTimeline();
661
+ 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);
669
+ }
670
+ } catch (error) {
671
+ if (error instanceof Error && !error.message.includes("not a function")) {
672
+ console.error("Error checking live status:", error);
673
+ }
674
+ }
675
+ };
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);
695
+ }
696
+ };
697
+ }, []);
698
+ const hideBadge = () => setIsVisible(false);
699
+ const showBadge = () => setIsVisible(true);
700
+ return {
701
+ isLive,
702
+ isVisible,
703
+ hideBadge,
704
+ showBadge,
705
+ checkLiveStatus
706
+ };
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(() => {
723
+ if (!containerRef.current || !enabled) {
724
+ return;
725
+ }
726
+ const addLiveIndicator = (currentTimeElement) => {
727
+ if (currentTimeElement.querySelector(".live-indicator-dot")) {
728
+ return;
729
+ }
730
+ const indicator = document.createElement("span");
731
+ indicator.className = "live-indicator-dot";
732
+ indicator.style.cssText = `
733
+ display: inline-block;
734
+ width: ${indicatorSize}px;
735
+ height: ${indicatorSize}px;
736
+ background-color: ${indicatorColor};
737
+ border-radius: 50%;
738
+ margin-right: 6px;
739
+ vertical-align: middle;
740
+ ${showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
741
+ `;
742
+ currentTimeElement.insertBefore(indicator, currentTimeElement.firstChild);
743
+ };
744
+ const removeLiveIndicator = (currentTimeElement) => {
745
+ const indicator = currentTimeElement.querySelector(".live-indicator-dot");
746
+ if (indicator) {
747
+ indicator.remove();
748
+ }
749
+ };
750
+ const checkForLiveContent = () => {
751
+ const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
752
+ currentTimeElements?.forEach((element) => {
753
+ const textContent = element.textContent?.trim() || "";
754
+ if (textContent.toLowerCase().includes("live")) {
755
+ addLiveIndicator(element);
756
+ } else {
757
+ removeLiveIndicator(element);
758
+ }
759
+ });
760
+ };
761
+ checkForLiveContent();
762
+ observerRef.current = new MutationObserver((mutations) => {
763
+ let shouldCheck = false;
764
+ mutations.forEach((mutation) => {
765
+ if (mutation.type === "childList" || mutation.type === "characterData") {
766
+ shouldCheck = true;
767
+ }
768
+ mutation.addedNodes.forEach((node) => {
769
+ if (node.nodeType === Node.ELEMENT_NODE) {
770
+ const element = node;
771
+ if (element.classList?.contains("shaka-current-time") || element.querySelector?.(".shaka-current-time")) {
772
+ shouldCheck = true;
773
+ }
774
+ }
775
+ });
776
+ });
777
+ if (shouldCheck) {
778
+ setTimeout(checkForLiveContent, 100);
779
+ }
780
+ });
781
+ observerRef.current.observe(containerRef.current, {
782
+ childList: true,
783
+ subtree: true,
784
+ characterData: true,
785
+ characterDataOldValue: true
786
+ });
787
+ const intervalId = setInterval(checkForLiveContent, 1e3);
788
+ return () => {
789
+ if (observerRef.current) {
790
+ observerRef.current.disconnect();
791
+ }
792
+ clearInterval(intervalId);
793
+ };
794
+ }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
795
+ 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")) {
802
+ }
803
+ });
804
+ }
805
+ };
806
+ };
807
+
808
+ // src/hooks/useShakaAbsoluteTime.ts
809
+ import { useEffect as useEffect4, useState as useState3 } from "react";
810
+ function useShakaAbsoluteTime({
811
+ player,
812
+ controls,
813
+ manualStreamStartDate
814
+ }) {
815
+ const [detectedStreamStart, setDetectedStreamStart] = useState3(null);
816
+ const detectStreamStartFromManifest = async () => {
817
+ if (!player) return null;
818
+ try {
819
+ const manifest = player.getManifest();
820
+ if (!manifest) return null;
821
+ const isLive = player.isLive();
822
+ if (!isLive) return null;
823
+ const video = player.getMediaElement();
824
+ if (video && video.seekable && video.seekable.length > 0) {
825
+ const seekableStart = video.seekable.start(0);
826
+ const seekableEnd = video.seekable.end(0);
827
+ const seekableDuration = seekableEnd - seekableStart;
828
+ const now = Date.now() / 1e3;
829
+ const estimatedStreamStart = now - seekableDuration;
830
+ return new Date(estimatedStreamStart * 1e3);
831
+ }
832
+ const stats = player.getStats();
833
+ if (stats && stats.manifestTimeSeconds) {
834
+ return new Date((Date.now() / 1e3 - stats.manifestTimeSeconds) * 1e3);
835
+ }
836
+ try {
837
+ const bufferedTimeRanges = video?.buffered;
838
+ if (bufferedTimeRanges && bufferedTimeRanges.length > 0) {
839
+ const totalBuffered = bufferedTimeRanges.end(bufferedTimeRanges.length - 1);
840
+ const now = Date.now() / 1e3;
841
+ return new Date((now - totalBuffered) * 1e3);
842
+ }
843
+ } catch (error) {
844
+ console.warn("Error extracting buffered timing info:", error);
845
+ }
846
+ console.warn("Could not detect stream start time from manifest");
847
+ return null;
848
+ } catch (error) {
849
+ console.warn("Error detecting stream start time:", error);
850
+ return null;
851
+ }
852
+ };
853
+ useEffect4(() => {
854
+ if (!player || manualStreamStartDate) return;
855
+ const detectStartTime = async () => {
856
+ setTimeout(async () => {
857
+ const detectedStart = await detectStreamStartFromManifest();
858
+ if (detectedStart) {
859
+ setDetectedStreamStart(detectedStart);
860
+ console.log("Detected stream start time:", detectedStart.toISOString());
861
+ }
862
+ }, 1e3);
863
+ };
864
+ const onManifestParsed = () => {
865
+ detectStartTime();
866
+ };
867
+ detectStartTime();
868
+ try {
869
+ player.addEventListener("manifestparsed", onManifestParsed);
870
+ player.addEventListener("streaming", onManifestParsed);
871
+ } catch (error) {
872
+ console.warn("Could not add manifest event listeners:", error);
873
+ }
874
+ return () => {
875
+ try {
876
+ player.removeEventListener("manifestparsed", onManifestParsed);
877
+ player.removeEventListener("streaming", onManifestParsed);
878
+ } catch (error) {
879
+ }
880
+ };
881
+ }, [player, manualStreamStartDate]);
882
+ const effectiveStreamStart = manualStreamStartDate || detectedStreamStart;
883
+ useEffect4(() => {
884
+ if (!player || !controls || !effectiveStreamStart) return;
885
+ const video = player.getMediaElement();
886
+ if (!video) return;
887
+ let originalGetDisplayTime;
888
+ let timeDisplayElement;
889
+ const formatElapsedTime = (elapsedSeconds) => {
890
+ const hours = Math.floor(elapsedSeconds / 3600);
891
+ const minutes = Math.floor(elapsedSeconds % 3600 / 60);
892
+ const seconds = Math.floor(elapsedSeconds % 60);
893
+ if (hours > 0) {
894
+ return [hours, minutes, seconds].map((val) => val.toString().padStart(2, "0")).join(":");
895
+ } else {
896
+ return [minutes, seconds].map((val) => val.toString().padStart(2, "0")).join(":");
897
+ }
898
+ };
899
+ const getElapsedTime = () => {
900
+ const now = /* @__PURE__ */ new Date();
901
+ const elapsedMs = now.getTime() - effectiveStreamStart.getTime();
902
+ return Math.max(0, elapsedMs / 1e3);
903
+ };
904
+ const customGetDisplayTime = function() {
905
+ const elapsedSeconds = getElapsedTime();
906
+ return formatElapsedTime(elapsedSeconds);
907
+ };
908
+ const setupTimeDisplayOverride = () => {
909
+ try {
910
+ const controlsContainer = controls.getControlsContainer();
911
+ if (!controlsContainer) return;
912
+ const timeDisplay = controlsContainer.querySelector(".shaka-current-time");
913
+ if (timeDisplay) {
914
+ timeDisplayElement = timeDisplay;
915
+ if (timeDisplayElement.getDisplayTime) {
916
+ originalGetDisplayTime = timeDisplayElement.getDisplayTime.bind(timeDisplayElement);
917
+ timeDisplayElement.getDisplayTime = customGetDisplayTime.bind(timeDisplayElement);
918
+ } else {
919
+ setupDirectTextUpdate();
920
+ }
921
+ }
922
+ } catch (error) {
923
+ console.warn("Error setting up time display override:", error);
924
+ setupDirectTextUpdate();
925
+ }
926
+ };
927
+ const setupDirectTextUpdate = () => {
928
+ let animationFrameId;
929
+ let isDestroyed = false;
930
+ const updateTimeDisplay = () => {
931
+ if (isDestroyed) return;
932
+ try {
933
+ const controlsContainer = controls.getControlsContainer();
934
+ if (controlsContainer) {
935
+ const currentTimeLabels = controlsContainer.querySelectorAll(".shaka-current-time");
936
+ const elapsedSeconds = getElapsedTime();
937
+ const timeText = formatElapsedTime(elapsedSeconds);
938
+ currentTimeLabels.forEach((label) => {
939
+ if (label && label.textContent !== timeText) {
940
+ label.textContent = timeText;
941
+ }
942
+ });
943
+ }
944
+ } catch (error) {
945
+ console.warn("Error updating time display:", error);
946
+ }
947
+ animationFrameId = requestAnimationFrame(updateTimeDisplay);
948
+ };
949
+ updateTimeDisplay();
950
+ return () => {
951
+ isDestroyed = true;
952
+ if (animationFrameId) {
953
+ cancelAnimationFrame(animationFrameId);
954
+ }
955
+ };
956
+ };
957
+ const setupSeekbarTooltip = () => {
958
+ try {
959
+ const controlsContainer = controls.getControlsContainer();
960
+ if (!controlsContainer) return;
961
+ const seekBar = controlsContainer.querySelector(".shaka-seek-bar");
962
+ if (!seekBar) return;
963
+ const onSeekBarMouseMove = (event) => {
964
+ const rect = seekBar.getBoundingClientRect();
965
+ const pos = (event.clientX - rect.left) / rect.width;
966
+ const totalElapsedSeconds = getElapsedTime();
967
+ const seekableRange = video.seekable;
968
+ if (seekableRange.length > 0) {
969
+ const seekableDuration = seekableRange.end(0) - seekableRange.start(0);
970
+ const positionInStream = totalElapsedSeconds - seekableDuration * (1 - pos);
971
+ const timeAtPosition = Math.max(0, positionInStream);
972
+ seekBar.title = formatElapsedTime(timeAtPosition);
973
+ } else {
974
+ seekBar.title = formatElapsedTime(totalElapsedSeconds);
975
+ }
976
+ };
977
+ seekBar.addEventListener("mousemove", onSeekBarMouseMove);
978
+ return () => {
979
+ seekBar.removeEventListener("mousemove", onSeekBarMouseMove);
980
+ };
981
+ } catch (error) {
982
+ console.warn("Error setting up seekbar tooltip:", error);
983
+ return () => {
984
+ };
985
+ }
986
+ };
987
+ const setupWithDelay = () => {
988
+ setTimeout(() => {
989
+ setupTimeDisplayOverride();
990
+ const cleanupSeekbar = setupSeekbarTooltip();
991
+ setupWithDelay.cleanupSeekbar = cleanupSeekbar;
992
+ }, 100);
993
+ };
994
+ setupWithDelay();
995
+ return () => {
996
+ if (timeDisplayElement && originalGetDisplayTime) {
997
+ try {
998
+ timeDisplayElement.getDisplayTime = originalGetDisplayTime;
999
+ } catch (error) {
1000
+ console.warn("Error restoring original getDisplayTime:", error);
1001
+ }
1002
+ }
1003
+ if (setupWithDelay.cleanupSeekbar) {
1004
+ setupWithDelay.cleanupSeekbar();
1005
+ }
1006
+ };
1007
+ }, [player, controls, effectiveStreamStart]);
1008
+ return {
1009
+ detectedStreamStart,
1010
+ effectiveStreamStart,
1011
+ isUsingManualDate: !!manualStreamStartDate
1012
+ };
1013
+ }
1014
+
1015
+ // src/components/Loading.tsx
1016
+ import { twMerge } from "tailwind-merge";
1017
+ import { jsx, jsxs } from "react/jsx-runtime";
1018
+ var Loading = ({ className }) => /* @__PURE__ */ jsxs(
1019
+ "div",
1020
+ {
1021
+ className: twMerge(
1022
+ "relative bg-[#151515] md:rounded-2xl! overflow-hidden aspect-video text-white w-full h-full flex justify-center items-center text-[10px]",
1023
+ className
1024
+ ),
1025
+ role: "status",
1026
+ children: [
1027
+ /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-white" }),
1028
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading..." })
1029
+ ]
1030
+ }
1031
+ );
1032
+
1033
+ // src/components/ErrorScreen.tsx
1034
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1035
+ 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: [
1036
+ /* @__PURE__ */ jsx2(
1037
+ "svg",
1038
+ {
1039
+ className: "w-24 h-24 m-6",
1040
+ fill: "none",
1041
+ stroke: "currentColor",
1042
+ strokeWidth: "2",
1043
+ style: { width: 96 },
1044
+ viewBox: "0 0 24 24",
1045
+ xmlns: "http://www.w3.org/2000/svg",
1046
+ children: /* @__PURE__ */ jsx2(
1047
+ "path",
1048
+ {
1049
+ d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z",
1050
+ strokeLinecap: "round",
1051
+ strokeLinejoin: "round"
1052
+ }
1053
+ )
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ jsxs2("div", { children: [
1057
+ /* @__PURE__ */ jsx2("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
1058
+ /* @__PURE__ */ jsx2("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
1059
+ ] })
1060
+ ] }) });
1061
+
1062
+ // src/components/Title.tsx
1063
+ import { jsx as jsx3 } from "react/jsx-runtime";
1064
+ 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 }) });
1065
+
1066
+ // src/components/LiveBadge.tsx
1067
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1068
+ var LiveBadge = ({
1069
+ isVisible,
1070
+ position = "top-right",
1071
+ className = "",
1072
+ style = {},
1073
+ text = "LIVE"
1074
+ }) => {
1075
+ if (!isVisible) return null;
1076
+ const positionClasses = {
1077
+ "top-left": "top-4 left-4",
1078
+ "top-right": "top-4 right-4",
1079
+ "bottom-left": "bottom-4 left-4",
1080
+ "bottom-right": "bottom-4 right-4"
1081
+ };
1082
+ return /* @__PURE__ */ jsx4(
1083
+ "div",
1084
+ {
1085
+ className: `
1086
+ absolute z-50
1087
+ ${positionClasses[position]}
1088
+ bg-red-600 text-white
1089
+ px-2 py-1
1090
+ rounded-md
1091
+ text-xs font-bold
1092
+ uppercase tracking-wide
1093
+ shadow-lg
1094
+ animate-pulse
1095
+ pointer-events-none
1096
+ ${className}
1097
+ `,
1098
+ style,
1099
+ children: /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1", children: [
1100
+ /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 bg-white rounded-full animate-pulse" }),
1101
+ text
1102
+ ] })
1103
+ }
1104
+ );
1105
+ };
1106
+
1107
+ // src/styles.css
1108
+ 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 .shaka-controls-container {\n z-index: 90 !important;\n height: 100px !important;\n bottom: 0 !important;\n top: unset !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');
1109
+
1110
+ // src/Player.tsx
1111
+ import { twMerge as twMerge2 } from "tailwind-merge";
1112
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1113
+ var Player = forwardRef(
1114
+ ({
1115
+ src,
1116
+ autoPlay = false,
1117
+ loop = false,
1118
+ muted = false,
1119
+ controls = true,
1120
+ poster,
1121
+ width,
1122
+ height,
1123
+ aspectRatio = 16 / 9,
1124
+ shakaConfig,
1125
+ drmConfig,
1126
+ muxConfig,
1127
+ imaConfig,
1128
+ chromecastConfig,
1129
+ qualityConfig,
1130
+ seekbarConfig,
1131
+ events,
1132
+ containerClassName,
1133
+ streamStartDate,
1134
+ ...props
1135
+ }, ref) => {
1136
+ const videoRef = useRef8(null);
1137
+ const containerRef = useRef8(null);
1138
+ const adContainerRef = useRef8(null);
1139
+ useImperativeHandle(ref, () => videoRef.current, []);
1140
+ const { playerRef, initializePlayer, destroyPlayer } = useShakePlayer({
1141
+ src,
1142
+ shakaConfig,
1143
+ drmConfig,
1144
+ onError: events?.onError,
1145
+ onPlayerReady: events?.onPlayerReady
1146
+ });
1147
+ const {
1148
+ getAvailableQualities,
1149
+ setQuality,
1150
+ setupQualityTracking,
1151
+ configureQuality
1152
+ } = useQualityControl(playerRef, qualityConfig, events?.onQualityChange);
1153
+ const {
1154
+ skipBack,
1155
+ skipForward,
1156
+ skipDuration,
1157
+ shouldShowSkipControls
1158
+ } = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
1159
+ const {
1160
+ initializeMux,
1161
+ updateMuxData,
1162
+ handleMuxError,
1163
+ destroyMux
1164
+ } = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
1165
+ const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
1166
+ onPlay: events?.onPlay,
1167
+ onPause: events?.onPause,
1168
+ onEnded: events?.onEnded,
1169
+ onLoadStart: events?.onLoadStart,
1170
+ onCanPlay: events?.onCanPlay
1171
+ });
1172
+ const { uiRef, initializeUI, destroyUI } = useShakaUI(
1173
+ playerRef,
1174
+ containerRef,
1175
+ videoRef,
1176
+ controls,
1177
+ chromecastConfig,
1178
+ seekbarConfig,
1179
+ events?.onSkipBack,
1180
+ events?.onSkipForward
1181
+ );
1182
+ const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
1183
+ enabled: true,
1184
+ onLiveStateChange: (isLive2) => {
1185
+ events?.onLiveStateChange?.(isLive2);
1186
+ }
1187
+ });
1188
+ useLiveIndicator(containerRef, {
1189
+ enabled: true,
1190
+ indicatorColor: "#ff0000",
1191
+ indicatorSize: 8,
1192
+ showPulseAnimation: true
1193
+ });
1194
+ const { detectedStreamStart, effectiveStreamStart } = useShakaAbsoluteTime({
1195
+ player: playerRef.current,
1196
+ controls: uiRef.current,
1197
+ manualStreamStartDate: streamStartDate
1198
+ });
1199
+ const initializeAds = () => {
1200
+ if (!imaConfig || !playerRef.current || !videoRef.current) return;
1201
+ const adManager = playerRef.current.getAdManager();
1202
+ if (!adManager) return;
1203
+ adManager.addEventListener(shaka2.ads?.Utils?.AD_STARTED, () => {
1204
+ events?.onAdStart?.();
1205
+ });
1206
+ adManager.addEventListener(shaka2.ads?.Utils?.AD_COMPLETE, () => {
1207
+ events?.onAdComplete?.();
1208
+ });
1209
+ adManager.addEventListener(shaka2.ads?.Utils?.AD_ERROR, (event) => {
1210
+ events?.onAdError?.(event.detail);
1211
+ });
1212
+ if (imaConfig.adTagUrl) {
1213
+ const adContainer = adContainerRef.current;
1214
+ if (adContainer) {
1215
+ adManager.initClientSide(adContainer, videoRef.current, imaConfig.adsRenderingSettings);
1216
+ const adsRequest = {
1217
+ adTagUrl: imaConfig.adTagUrl,
1218
+ linearAdSlotWidth: imaConfig.linearAdSlotWidth || width || 640,
1219
+ linearAdSlotHeight: imaConfig.linearAdSlotHeight || height || 360,
1220
+ nonLinearAdSlotWidth: imaConfig.nonLinearAdSlotWidth || width || 640,
1221
+ nonLinearAdSlotHeight: imaConfig.nonLinearAdSlotHeight || 150
1222
+ };
1223
+ adManager.requestClientSideAds(adsRequest);
1224
+ }
1225
+ }
1226
+ };
1227
+ const initializeChromecast = () => {
1228
+ if (!chromecastConfig?.enabled) {
1229
+ return;
1230
+ }
1231
+ try {
1232
+ if (events?.onCastStateChange) {
1233
+ setTimeout(() => events.onCastStateChange(false), 100);
1234
+ }
1235
+ } catch (error) {
1236
+ console.warn("Chromecast initialization failed:", error);
1237
+ }
1238
+ };
1239
+ useEffect5(() => {
1240
+ const video = videoRef.current;
1241
+ if (!video) return;
1242
+ const initialize = async () => {
1243
+ try {
1244
+ await initializePlayer(video);
1245
+ setupEventListeners();
1246
+ const cleanupQuality = setupQualityTracking();
1247
+ configureQuality();
1248
+ await initializeUI();
1249
+ initializeMux();
1250
+ initializeAds();
1251
+ initializeChromecast();
1252
+ } catch (error) {
1253
+ console.error("Error during player initialization:", error);
1254
+ handleMuxError(error);
1255
+ }
1256
+ };
1257
+ initialize();
1258
+ return () => {
1259
+ cleanupEventListeners();
1260
+ destroyUI();
1261
+ destroyMux();
1262
+ destroyPlayer();
1263
+ };
1264
+ }, [
1265
+ src,
1266
+ initializePlayer,
1267
+ setupEventListeners,
1268
+ setupQualityTracking,
1269
+ configureQuality,
1270
+ initializeUI,
1271
+ initializeMux,
1272
+ cleanupEventListeners,
1273
+ destroyUI,
1274
+ destroyMux,
1275
+ destroyPlayer,
1276
+ handleMuxError,
1277
+ playerRef
1278
+ ]);
1279
+ useEffect5(() => {
1280
+ const video = videoRef.current;
1281
+ if (!video) return;
1282
+ video.autoplay = autoPlay;
1283
+ video.loop = loop;
1284
+ video.muted = muted;
1285
+ video.controls = false;
1286
+ if (poster) video.poster = poster;
1287
+ }, [autoPlay, loop, muted, poster]);
1288
+ useImperativeHandle(ref, () => ({
1289
+ ...videoRef.current,
1290
+ // Custom methods for quality control
1291
+ getAvailableQualities,
1292
+ setQuality,
1293
+ // Skip methods
1294
+ skipBack,
1295
+ skipForward,
1296
+ // Mux methods
1297
+ updateMuxData,
1298
+ // Access to underlying instances
1299
+ getPlayer: () => playerRef.current,
1300
+ getMuxMonitor: () => null
1301
+ }), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData]);
1302
+ const isResponsive = !width && !height;
1303
+ const containerClasses = twMerge2(containerClassName, "motto-video-container");
1304
+ const containerStyle = isResponsive ? {
1305
+ aspectRatio: aspectRatio.toString()
1306
+ } : { width, height };
1307
+ const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
1308
+ const videoStyle = isResponsive ? {} : { width, height };
1309
+ return /* @__PURE__ */ jsxs4(
1310
+ "div",
1311
+ {
1312
+ ref: containerRef,
1313
+ className: containerClasses,
1314
+ style: containerStyle,
1315
+ "data-shaka-player-container": true,
1316
+ "data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
1317
+ children: [
1318
+ /* @__PURE__ */ jsx5(
1319
+ "video",
1320
+ {
1321
+ ref: videoRef,
1322
+ className: videoClasses,
1323
+ width: isResponsive ? void 0 : width,
1324
+ height: isResponsive ? void 0 : height,
1325
+ style: videoStyle,
1326
+ controls: false,
1327
+ ...props
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsx5(LiveBadge, { isVisible: isLiveBadgeVisible }),
1331
+ imaConfig && /* @__PURE__ */ jsx5(
1332
+ "div",
1333
+ {
1334
+ ref: adContainerRef,
1335
+ className: "absolute top-0 left-0 w-full h-full pointer-events-auto"
1336
+ }
1337
+ )
1338
+ ]
1339
+ }
1340
+ );
1341
+ }
1342
+ );
1343
+ Player.displayName = "Player";
1344
+
1345
+ // src/Video.tsx
1346
+ import { useEffect as useEffect7 } from "react";
1347
+ import { twMerge as twMerge3 } from "tailwind-merge";
1348
+ import { useQuery } from "@tanstack/react-query";
1349
+
1350
+ // src/api/video.ts
1351
+ var fetchVideoData = async (videoId, publicKey, mottoToken) => {
1352
+ const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/GetVideo";
1353
+ const url = new URL(endpoint);
1354
+ url.searchParams.set("encoding", "json");
1355
+ url.searchParams.set("message", JSON.stringify({ videoId }));
1356
+ const response = await fetch(url, {
1357
+ method: "GET",
1358
+ headers: {
1359
+ Authorization: `Bearer ${publicKey}`,
1360
+ ...Boolean(mottoToken) && { "x-motto-token": mottoToken }
1361
+ }
1362
+ });
1363
+ if (!response.ok) {
1364
+ throw new Error(`Failed to fetch video: ${response.statusText}`);
1365
+ }
1366
+ const data = await response.json();
1367
+ return data.video;
1368
+ };
1369
+ async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0) {
1370
+ if (!videoIds || videoIds.length === 0) {
1371
+ return [];
1372
+ }
1373
+ const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/BatchGetVideos";
1374
+ const url = new URL(endpoint);
1375
+ url.searchParams.set("encoding", "json");
1376
+ url.searchParams.set("message", JSON.stringify({ videoIds }));
1377
+ const response = await fetch(url.toString(), {
1378
+ method: "GET",
1379
+ headers: {
1380
+ Authorization: `Bearer ${publicKey}`,
1381
+ ...Boolean(mottoToken) && { "x-motto-token": mottoToken }
1382
+ }
1383
+ }).catch((err) => {
1384
+ throw new Error(`Failed to fetch videos: ${err}`);
1385
+ });
1386
+ if (!response.ok) {
1387
+ throw new Error(`Failed to fetch videos list: ${response.status}`);
1388
+ }
1389
+ const data = await response.json();
1390
+ return data.videos;
1391
+ }
1392
+
1393
+ // src/api/event.ts
1394
+ async function fetchEventData(publicKey, eventId, unused, filter, order, locale) {
1395
+ const endpoint = "https://cda.mottostreaming.com/motto.cda.cms.event.v1.EventService/GetEvent";
1396
+ const url = new URL(endpoint);
1397
+ const message = { eventId };
1398
+ if (locale?.length) message.locale = locale;
1399
+ if (filter) message.filter = filter;
1400
+ if (order) message.order = order;
1401
+ url.searchParams.set("encoding", "json");
1402
+ url.searchParams.set("message", JSON.stringify(message));
1403
+ const response = await fetch(url.toString(), {
1404
+ method: "GET",
1405
+ headers: {
1406
+ Authorization: `Bearer ${publicKey}`
1407
+ }
1408
+ }).catch((err) => {
1409
+ throw new Error(`Failed to fetch event: ${err}`);
1410
+ });
1411
+ if (!response.ok) {
1412
+ throw new Error(`Failed to fetch event data: ${response.status}`);
1413
+ }
1414
+ const data = await response.json();
1415
+ return data.event;
1416
+ }
1417
+
1418
+ // src/api/creative-work.ts
1419
+ async function fetchCreativeWorkData(publicKey, creativeWorkId, unused, filter, order, locale) {
1420
+ const endpoint = "https://cda.mottostreaming.com/motto.cda.cms.creative_work.v1.CreativeWorkService/GetCreativeWork";
1421
+ const url = new URL(endpoint);
1422
+ const message = { creativeWorkId };
1423
+ if (locale?.length) message.locale = locale;
1424
+ if (filter) message.filter = filter;
1425
+ if (order) message.order = order;
1426
+ url.searchParams.set("encoding", "json");
1427
+ url.searchParams.set("message", JSON.stringify(message));
1428
+ const response = await fetch(url.toString(), {
1429
+ method: "GET",
1430
+ headers: {
1431
+ Authorization: `Bearer ${publicKey}`
1432
+ }
1433
+ }).catch((err) => {
1434
+ throw new Error(`Failed to fetch creative work: ${err}`);
1435
+ });
1436
+ if (!response.ok) {
1437
+ throw new Error(`Failed to fetch creative work data: ${response.status}`);
1438
+ }
1439
+ const data = await response.json();
1440
+ return data.creativeWork;
1441
+ }
1442
+
1443
+ // src/helper.ts
1444
+ var defaultError = {
1445
+ title: "Playback Error",
1446
+ description: "Unable to play the video. Please try again later."
1447
+ };
1448
+ var errorTypes = {
1449
+ api: {
1450
+ title: "Failed to Retrieve Video Info",
1451
+ description: "Error fetching video details. Check your videoId and internet connection and try again."
1452
+ },
1453
+ ERROR_CODE_NOT_AUTHENTICATED: {
1454
+ title: "Authorisation",
1455
+ description: "You don't have permission to play this video. "
1456
+ },
1457
+ ERROR_CODE_GEO_BLOCKED: {
1458
+ title: "Geoblocking Restriction",
1459
+ description: "Sorry, this video is not available in your region due to geoblocking restrictions."
1460
+ },
1461
+ ERROR_CODE_NOT_ENTITLED: {
1462
+ title: "Not entitled",
1463
+ description: "Sorry, you are not entitled to play this video."
1464
+ },
1465
+ ERROR_CODE_VPN_BLOCKED: {
1466
+ title: "VPN BLOCKED",
1467
+ description: "This video is not available due to the use of a VPN."
1468
+ },
1469
+ ERROR_CODE_UNSPECIFIED: defaultError,
1470
+ ERROR_CODE_SIGNATURE_MISMATCH: defaultError,
1471
+ ERROR_CODE_INVALID_DOMAIN: defaultError,
1472
+ default: defaultError
1473
+ };
1474
+ var findHLSPlaylist = (video) => {
1475
+ return video?.playlists?.find((playlist) => {
1476
+ return playlist.format === "HLS" || playlist.format === "hls" || playlist.format === "PLAYLIST_FORMAT_HLS";
1477
+ });
1478
+ };
1479
+ var getErrorType = (error, video) => {
1480
+ if (video?.error && errorTypes[video.error]) {
1481
+ return video.error;
1482
+ }
1483
+ return "DEFAULT_ERROR";
1484
+ };
1485
+
1486
+ // src/messages/useMessages.tsx
1487
+ import { useState as useState4, useEffect as useEffect6 } from "react";
1488
+
1489
+ // src/messages/en.json
1490
+ var en_default = {
1491
+ DAYS: "days",
1492
+ HOURS: "hours",
1493
+ MINUTES: "min",
1494
+ SECONDS: "sec",
1495
+ STARTING_SOON: "Starting soon...",
1496
+ EVENT_NOT_STARTED: "This event has not started...",
1497
+ DEFAULT_ERROR: "Playback Error",
1498
+ DEFAULT_ERROR_DESCRIPTION: "Unable to play the video. Please try again later.",
1499
+ API_ERROR: "Failed to Retrieve Video Info",
1500
+ API_ERROR_DESCRIPTION: "Error fetching video details. Check your videoId and internet connection and try again.",
1501
+ ERROR_CODE_NOT_AUTHENTICATED: "Authorisation",
1502
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "You don't have permission to play this video.",
1503
+ ERROR_CODE_GEO_BLOCKED: "Geoblocking Restriction",
1504
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Sorry, this video is not available in your region due to geoblocking restrictions.",
1505
+ ERROR_CODE_NOT_ENTITLED: "Not entitled",
1506
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Sorry, you are not entitled to play this video.",
1507
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOCKED",
1508
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "This video is not available due to the use of a VPN."
1509
+ };
1510
+
1511
+ // src/messages/es.json
1512
+ var es_default = {
1513
+ DAYS: "d\xEDas",
1514
+ HOURS: "horas",
1515
+ MINUTES: "min",
1516
+ SECONDS: "seg",
1517
+ STARTING_SOON: "En instantes...",
1518
+ EVENT_NOT_STARTED: "Este evento a\xFAn no ha comenzado...",
1519
+ DEFAULT_ERROR: "Error de reproducci\xF3n",
1520
+ DEFAULT_ERROR_DESCRIPTION: "No se puede reproducir el video. Por favor, int\xE9ntelo de nuevo m\xE1s tarde.",
1521
+ API_ERROR: "Error al recuperar informaci\xF3n del video",
1522
+ API_ERROR_DESCRIPTION: "Error al obtener detalles del video. Verifique su videoId y conexi\xF3n a internet e int\xE9ntelo de nuevo.",
1523
+ ERROR_CODE_NOT_AUTHENTICATED: "Autorizaci\xF3n",
1524
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "No tienes permiso para reproducir este video.",
1525
+ ERROR_CODE_GEO_BLOCKED: "Restricci\xF3n geogr\xE1fica",
1526
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Lo siento, este video no est\xE1 disponible en tu regi\xF3n debido a restricciones geogr\xE1ficas.",
1527
+ ERROR_CODE_NOT_ENTITLED: "No autorizado",
1528
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Lo siento, no est\xE1s autorizado para reproducir este video.",
1529
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOQUEADO",
1530
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Este video no est\xE1 disponible debido al uso de una VPN."
1531
+ };
1532
+
1533
+ // src/messages/ar.json
1534
+ var ar_default = {
1535
+ DAYS: "\u0623\u064A\u0627\u0645",
1536
+ HOURS: "\u0633\u0627\u0639\u0627\u062A",
1537
+ MINUTES: "\u062F\u0642\u0627\u0626\u0642",
1538
+ SECONDS: "\u062B\u0648\u0627\u0646\u064A",
1539
+ STARTING_SOON: "\u064A\u0628\u062F\u0623 \u0642\u0631\u064A\u0628\u0627...",
1540
+ EVENT_NOT_STARTED: "\u0647\u0630\u0627 \u0627\u0644\u062D\u062F\u062B \u0644\u0645 \u064A\u0628\u062F\u0623 \u0628\u0639\u062F...",
1541
+ DEFAULT_ERROR: "\u062E\u0637\u0623 \u0641\u064A \u0627\u0644\u062A\u0634\u063A\u064A\u0644",
1542
+ DEFAULT_ERROR_DESCRIPTION: "\u063A\u064A\u0631 \u0642\u0627\u062F\u0631 \u0639\u0644\u0649 \u062A\u0634\u063A\u064A\u0644 \u0627\u0644\u0641\u064A\u062F\u064A\u0648. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0644\u0627\u062D\u0642\u064B\u0627.",
1543
+ API_ERROR: "\u0641\u0634\u0644 \u0641\u064A \u0627\u0633\u062A\u0631\u062C\u0627\u0639 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
1544
+ API_ERROR_DESCRIPTION: "\u062E\u0637\u0623 \u0641\u064A \u062C\u0644\u0628 \u062A\u0641\u0627\u0635\u064A\u0644 \u0627\u0644\u0641\u064A\u062F\u064A\u0648. \u062A\u062D\u0642\u0642 \u0645\u0646 \u0645\u0639\u0631\u0641 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0648\u0627\u062A\u0635\u0627\u0644 \u0627\u0644\u0625\u0646\u062A\u0631\u0646\u062A \u0648\u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
1545
+ ERROR_CODE_NOT_AUTHENTICATED: "\u062A\u0641\u0648\u064A\u0636",
1546
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\u0644\u064A\u0633 \u0644\u062F\u064A\u0643 \u0625\u0630\u0646 \u0644\u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648.",
1547
+ ERROR_CODE_GEO_BLOCKED: "\u0642\u064A\u0648\u062F \u0627\u0644\u062C\u063A\u0631\u0627\u0641\u064A\u0627",
1548
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\u0639\u0630\u0631\u064B\u0627\u060C \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D \u0641\u064A \u0645\u0646\u0637\u0642\u062A\u0643 \u0628\u0633\u0628\u0628 \u0642\u064A\u0648\u062F \u0627\u0644\u062C\u063A\u0631\u0627\u0641\u064A\u0627.",
1549
+ ERROR_CODE_NOT_ENTITLED: "\u063A\u064A\u0631 \u0645\u062E\u0648\u0644",
1550
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\u0639\u0630\u0631\u064B\u0627\u060C \u0644\u064A\u0633 \u0644\u062F\u064A\u0643 \u0627\u0644\u062D\u0642 \u0641\u064A \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648.",
1551
+ ERROR_CODE_VPN_BLOCKED: "\u062A\u0645 \u062D\u0638\u0631 VPN",
1552
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "\u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u063A\u064A\u0631 \u0645\u062A\u0627\u062D \u0628\u0633\u0628\u0628 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 VPN."
1553
+ };
1554
+
1555
+ // src/messages/de.json
1556
+ var de_default = {
1557
+ DAYS: "Tage",
1558
+ HOURS: "Stunden",
1559
+ MINUTES: "Min",
1560
+ SECONDS: "Sek",
1561
+ STARTING_SOON: "Beginnt bald...",
1562
+ DEFAULT_ERROR: "Wiedergabefehler",
1563
+ DEFAULT_ERROR_DESCRIPTION: "Das Video kann nicht abgespielt werden. Bitte versuchen Sie es sp\xE4ter erneut.",
1564
+ API_ERROR: "Fehler beim Abrufen der Videoinformationen",
1565
+ API_ERROR_DESCRIPTION: "Fehler beim Abrufen der Videodetails. \xDCberpr\xFCfen Sie Ihre videoId und Internetverbindung und versuchen Sie es erneut.",
1566
+ ERROR_CODE_NOT_AUTHENTICATED: "Autorisierung",
1567
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "Sie haben keine Berechtigung, dieses Video abzuspielen.",
1568
+ ERROR_CODE_GEO_BLOCKED: "Geoblocking-Beschr\xE4nkung",
1569
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Entschuldigung, dieses Video ist in Ihrer Region aufgrund von Geoblocking-Beschr\xE4nkungen nicht verf\xFCgbar.",
1570
+ ERROR_CODE_NOT_ENTITLED: "Nicht berechtigt",
1571
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Entschuldigung, Sie sind nicht berechtigt, dieses Video abzuspielen.",
1572
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOCKIERT",
1573
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Dieses Video ist aufgrund der Verwendung eines VPN nicht verf\xFCgbar."
1574
+ };
1575
+
1576
+ // src/messages/fr.json
1577
+ var fr_default = {
1578
+ DAYS: "jours",
1579
+ HOURS: "heures",
1580
+ MINUTES: "minutes",
1581
+ SECONDS: "secondes",
1582
+ STARTING_SOON: "Commence bient\xF4t...",
1583
+ EVENT_NOT_STARTED: "Cet \xE9v\xE9nement n'a pas commenc\xE9...",
1584
+ DEFAULT_ERROR: "Erreur de lecture",
1585
+ DEFAULT_ERROR_DESCRIPTION: "Impossible de lire la vid\xE9o. Veuillez r\xE9essayer plus tard.",
1586
+ API_ERROR: "\xC9chec de la r\xE9cup\xE9ration des informations vid\xE9o",
1587
+ API_ERROR_DESCRIPTION: "Erreur lors de la r\xE9cup\xE9ration des d\xE9tails de la vid\xE9o. V\xE9rifiez votre videoId et votre connexion Internet, puis r\xE9essayez.",
1588
+ ERROR_CODE_NOT_AUTHENTICATED: "Autorisation",
1589
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "Vous n'avez pas la permission de lire cette vid\xE9o.",
1590
+ ERROR_CODE_GEO_BLOCKED: "Restriction de g\xE9oblocage",
1591
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "D\xE9sol\xE9, cette vid\xE9o n'est pas disponible dans votre r\xE9gion en raison de restrictions de g\xE9oblocage.",
1592
+ ERROR_CODE_NOT_ENTITLED: "Non autoris\xE9",
1593
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "D\xE9sol\xE9, vous n'\xEAtes pas autoris\xE9 \xE0 lire cette vid\xE9o.",
1594
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOQU\xC9",
1595
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Cette vid\xE9o n'est pas disponible en raison de l'utilisation d'un VPN."
1596
+ };
1597
+
1598
+ // src/messages/it.json
1599
+ var it_default = {
1600
+ DAYS: "giorni",
1601
+ HOURS: "ore",
1602
+ MINUTES: "minuti",
1603
+ SECONDS: "secondi",
1604
+ STARTING_SOON: "Inizia presto...",
1605
+ DEFAULT_ERROR: "Errore di riproduzione",
1606
+ DEFAULT_ERROR_DESCRIPTION: "Impossibile riprodurre il video. Per favore riprova pi\xF9 tardi.",
1607
+ API_ERROR: "Errore nel recupero delle informazioni video",
1608
+ API_ERROR_DESCRIPTION: "Errore nel recupero dei dettagli del video. Controlla il tuo videoId e la connessione internet e riprova.",
1609
+ ERROR_CODE_NOT_AUTHENTICATED: "Autorizzazione",
1610
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "Non hai il permesso di riprodurre questo video.",
1611
+ ERROR_CODE_GEO_BLOCKED: "Restrizione geoblocking",
1612
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Spiacenti, questo video non \xE8 disponibile nella tua regione a causa di restrizioni geografiche.",
1613
+ ERROR_CODE_NOT_ENTITLED: "Non autorizzato",
1614
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Spiacenti, non sei autorizzato a riprodurre questo video.",
1615
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOCCATA",
1616
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Questo video non \xE8 disponibile a causa dell'uso di una VPN."
1617
+ };
1618
+
1619
+ // src/messages/ja.json
1620
+ var ja_default = {
1621
+ DAYS: "\u65E5",
1622
+ HOURS: "\u6642\u9593",
1623
+ MINUTES: "\u5206",
1624
+ SECONDS: "\u79D2",
1625
+ STARTING_SOON: "\u307E\u3082\u306A\u304F\u958B\u59CB...",
1626
+ DEFAULT_ERROR: "\u518D\u751F\u30A8\u30E9\u30FC",
1627
+ DEFAULT_ERROR_DESCRIPTION: "\u30D3\u30C7\u30AA\u3092\u518D\u751F\u3067\u304D\u307E\u305B\u3093\u3002\u5F8C\u3067\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
1628
+ API_ERROR: "\u30D3\u30C7\u30AA\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
1629
+ API_ERROR_DESCRIPTION: "\u30D3\u30C7\u30AA\u306E\u8A73\u7D30\u3092\u53D6\u5F97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002videoId\u3068\u30A4\u30F3\u30BF\u30FC\u30CD\u30C3\u30C8\u63A5\u7D9A\u3092\u78BA\u8A8D\u3057\u3066\u3001\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
1630
+ ERROR_CODE_NOT_AUTHENTICATED: "\u8A8D\u8A3C",
1631
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\u3053\u306E\u30D3\u30C7\u30AA\u3092\u518D\u751F\u3059\u308B\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
1632
+ ERROR_CODE_GEO_BLOCKED: "\u5730\u57DF\u5236\u9650",
1633
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\u7533\u3057\u8A33\u3042\u308A\u307E\u305B\u3093\u304C\u3001\u5730\u57DF\u5236\u9650\u306E\u305F\u3081\u3053\u306E\u30D3\u30C7\u30AA\u306F\u3054\u5229\u7528\u3044\u305F\u3060\u3051\u307E\u305B\u3093\u3002",
1634
+ ERROR_CODE_NOT_ENTITLED: "\u6A29\u5229\u306A\u3057",
1635
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\u7533\u3057\u8A33\u3042\u308A\u307E\u305B\u3093\u304C\u3001\u3053\u306E\u30D3\u30C7\u30AA\u3092\u518D\u751F\u3059\u308B\u6A29\u5229\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
1636
+ ERROR_CODE_VPN_BLOCKED: "VPN\u30D6\u30ED\u30C3\u30AF",
1637
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "VPN\u306E\u4F7F\u7528\u306B\u3088\u308A\u3001\u3053\u306E\u30D3\u30C7\u30AA\u306F\u3054\u5229\u7528\u3044\u305F\u3060\u3051\u307E\u305B\u3093\u3002"
1638
+ };
1639
+
1640
+ // src/messages/ko.json
1641
+ var ko_default = {
1642
+ DAYS: "\uC77C",
1643
+ HOURS: "\uC2DC\uAC04",
1644
+ MINUTES: "\uBD84",
1645
+ SECONDS: "\uCD08",
1646
+ STARTING_SOON: "\uACE7 \uC2DC\uC791...",
1647
+ DEFAULT_ERROR: "\uC7AC\uC0DD \uC624\uB958",
1648
+ DEFAULT_ERROR_DESCRIPTION: "\uBE44\uB514\uC624\uB97C \uC7AC\uC0DD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.",
1649
+ API_ERROR: "\uBE44\uB514\uC624 \uC815\uBCF4 \uAC00\uC838\uC624\uAE30 \uC2E4\uD328",
1650
+ API_ERROR_DESCRIPTION: "\uBE44\uB514\uC624 \uC138\uBD80 \uC815\uBCF4\uB97C \uAC00\uC838\uC624\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. videoId\uC640 \uC778\uD130\uB137 \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uACE0 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.",
1651
+ ERROR_CODE_NOT_AUTHENTICATED: "\uC778\uC99D",
1652
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\uC774 \uBE44\uB514\uC624\uB97C \uC7AC\uC0DD\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
1653
+ ERROR_CODE_GEO_BLOCKED: "\uC9C0\uC5ED \uC81C\uD55C",
1654
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\uC8C4\uC1A1\uD569\uB2C8\uB2E4. \uC774 \uBE44\uB514\uC624\uB294 \uC9C0\uC5ED \uC81C\uD55C\uC73C\uB85C \uC778\uD574 \uADC0\uD558\uC758 \uC9C0\uC5ED\uC5D0\uC11C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
1655
+ ERROR_CODE_NOT_ENTITLED: "\uAD8C\uD55C \uC5C6\uC74C",
1656
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\uC8C4\uC1A1\uD569\uB2C8\uB2E4. \uC774 \uBE44\uB514\uC624\uB97C \uC7AC\uC0DD\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
1657
+ ERROR_CODE_VPN_BLOCKED: "VPN \uCC28\uB2E8\uB428",
1658
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "VPN \uC0AC\uC6A9\uC73C\uB85C \uC778\uD574 \uC774 \uBE44\uB514\uC624\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
1659
+ };
1660
+
1661
+ // src/messages/pt.json
1662
+ var pt_default = {
1663
+ DAYS: "dias",
1664
+ HOURS: "horas",
1665
+ MINUTES: "minutos",
1666
+ SECONDS: "segundos",
1667
+ STARTING_SOON: "Come\xE7ando em breve...",
1668
+ DEFAULT_ERROR: "Playback Error",
1669
+ DEFAULT_ERROR_DESCRIPTION: "N\xE3o foi poss\xEDvel reproduzir o v\xEDdeo. Por favor, tente novamente mais tarde.",
1670
+ API_ERROR: "Falha ao Recuperar Informa\xE7\xF5es do V\xEDdeo",
1671
+ API_ERROR_DESCRIPTION: "Erro ao buscar detalhes do v\xEDdeo. Verifique seu videoId e conex\xE3o com a internet e tente novamente.",
1672
+ ERROR_CODE_NOT_AUTHENTICATED: "Autoriza\xE7\xE3o",
1673
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "Voc\xEA n\xE3o tem permiss\xE3o para reproduzir este v\xEDdeo.",
1674
+ ERROR_CODE_GEO_BLOCKED: "Restri\xE7\xE3o de Geoblocking",
1675
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Desculpe, este v\xEDdeo n\xE3o est\xE1 dispon\xEDvel em sua regi\xE3o devido a restri\xE7\xF5es de geoblocking.",
1676
+ ERROR_CODE_NOT_ENTITLED: "N\xE3o autorizado",
1677
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Desculpe, voc\xEA n\xE3o est\xE1 autorizado a reproduzir este v\xEDdeo.",
1678
+ ERROR_CODE_VPN_BLOCKED: "VPN BLOQUEADO",
1679
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Este v\xEDdeo n\xE3o est\xE1 dispon\xEDvel devido ao uso de uma VPN."
1680
+ };
1681
+
1682
+ // src/messages/ru.json
1683
+ var ru_default = {
1684
+ DAYS: "\u0434\u043D\u0435\u0439",
1685
+ HOURS: "\u0447\u0430\u0441\u043E\u0432",
1686
+ MINUTES: "\u043C\u0438\u043D",
1687
+ SECONDS: "\u0441\u0435\u043A",
1688
+ STARTING_SOON: "\u0421\u043A\u043E\u0440\u043E \u043D\u0430\u0447\u043D\u0435\u0442\u0441\u044F...",
1689
+ DEFAULT_ERROR: "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u044F",
1690
+ DEFAULT_ERROR_DESCRIPTION: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432\u0438\u0434\u0435\u043E. \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.",
1691
+ API_ERROR: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u043E \u0432\u0438\u0434\u0435\u043E",
1692
+ API_ERROR_DESCRIPTION: "\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0438 \u0434\u0435\u0442\u0430\u043B\u0435\u0439 \u0432\u0438\u0434\u0435\u043E. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0432\u0430\u0448 videoId \u0438 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u043A \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0443, \u0437\u0430\u0442\u0435\u043C \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0441\u043D\u043E\u0432\u0430.",
1693
+ ERROR_CODE_NOT_AUTHENTICATED: "\u0410\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F",
1694
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\u0423 \u0432\u0430\u0441 \u043D\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043D\u0430 \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u044D\u0442\u043E\u0433\u043E \u0432\u0438\u0434\u0435\u043E.",
1695
+ ERROR_CODE_GEO_BLOCKED: "\u0413\u0435\u043E\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u043E\u0435 \u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D\u0438\u0435",
1696
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\u0418\u0437\u0432\u0438\u043D\u0438\u0442\u0435, \u044D\u0442\u043E \u0432\u0438\u0434\u0435\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u0432 \u0432\u0430\u0448\u0435\u043C \u0440\u0435\u0433\u0438\u043E\u043D\u0435 \u0438\u0437-\u0437\u0430 \u0433\u0435\u043E\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u0438\u0445 \u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D\u0438\u0439.",
1697
+ ERROR_CODE_NOT_ENTITLED: "\u041D\u0435\u0442 \u043F\u0440\u0430\u0432",
1698
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\u0418\u0437\u0432\u0438\u043D\u0438\u0442\u0435, \u0443 \u0432\u0430\u0441 \u043D\u0435\u0442 \u043F\u0440\u0430\u0432 \u043D\u0430 \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u044D\u0442\u043E\u0433\u043E \u0432\u0438\u0434\u0435\u043E.",
1699
+ ERROR_CODE_VPN_BLOCKED: "VPN \u0437\u0430\u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u043D",
1700
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "\u042D\u0442\u043E \u0432\u0438\u0434\u0435\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u0438\u0437-\u0437\u0430 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F VPN."
1701
+ };
1702
+
1703
+ // src/messages/zh.json
1704
+ var zh_default = {
1705
+ DAYS: "\u5929",
1706
+ HOURS: "\u5C0F\u65F6",
1707
+ MINUTES: "\u5206\u949F",
1708
+ SECONDS: "\u79D2",
1709
+ STARTING_SOON: "\u5373\u5C06\u5F00\u59CB...",
1710
+ DEFAULT_ERROR: "\u64AD\u653E\u9519\u8BEF",
1711
+ DEFAULT_ERROR_DESCRIPTION: "\u65E0\u6CD5\u64AD\u653E\u89C6\u9891\u3002\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002",
1712
+ API_ERROR: "\u83B7\u53D6\u89C6\u9891\u4FE1\u606F\u5931\u8D25",
1713
+ API_ERROR_DESCRIPTION: "\u83B7\u53D6\u89C6\u9891\u8BE6\u60C5\u65F6\u51FA\u9519\u3002\u8BF7\u68C0\u67E5\u60A8\u7684\u89C6\u9891ID\u548C\u4E92\u8054\u7F51\u8FDE\u63A5\uFF0C\u7136\u540E\u91CD\u8BD5\u3002",
1714
+ ERROR_CODE_NOT_AUTHENTICATED: "\u6388\u6743",
1715
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\u60A8\u6CA1\u6709\u6743\u9650\u64AD\u653E\u6B64\u89C6\u9891\u3002",
1716
+ ERROR_CODE_GEO_BLOCKED: "\u5730\u7406\u5C01\u9501\u9650\u5236",
1717
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\u62B1\u6B49\uFF0C\u7531\u4E8E\u5730\u7406\u5C01\u9501\u9650\u5236\uFF0C\u6B64\u89C6\u9891\u5728\u60A8\u7684\u5730\u533A\u4E0D\u53EF\u7528\u3002",
1718
+ ERROR_CODE_NOT_ENTITLED: "\u65E0\u6743\u64AD\u653E",
1719
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\u62B1\u6B49\uFF0C\u60A8\u65E0\u6743\u64AD\u653E\u6B64\u89C6\u9891\u3002",
1720
+ ERROR_CODE_VPN_BLOCKED: "VPN\u88AB\u5C01\u9501",
1721
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "\u7531\u4E8E\u4F7F\u7528VPN\uFF0C\u6B64\u89C6\u9891\u4E0D\u53EF\u7528\u3002"
1722
+ };
1723
+
1724
+ // src/messages/nl.json
1725
+ var nl_default = {
1726
+ DAYS: "dagen",
1727
+ HOURS: "uren",
1728
+ MINUTES: "min",
1729
+ SECONDS: "sec",
1730
+ STARTING_SOON: "Begint binnenkort...",
1731
+ EVENT_NOT_STARTED: "Dit evenement is nog niet begonnen...",
1732
+ DEFAULT_ERROR: "Afspelfout",
1733
+ DEFAULT_ERROR_DESCRIPTION: "Kan de video niet afspelen. Probeer het later opnieuw.",
1734
+ API_ERROR: "Kan videogegevens niet ophalen",
1735
+ API_ERROR_DESCRIPTION: "Fout bij het ophalen van videogegevens. Controleer uw video-ID en internetverbinding en probeer het opnieuw.",
1736
+ ERROR_CODE_NOT_AUTHENTICATED: "Autorisatie",
1737
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "U heeft geen toestemming om deze video af te spelen.",
1738
+ ERROR_CODE_GEO_BLOCKED: "Geoblocking Beperking",
1739
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "Sorry, deze video is niet beschikbaar in uw regio vanwege geoblocking beperkingen.",
1740
+ ERROR_CODE_NOT_ENTITLED: "Geen recht",
1741
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "Sorry, u heeft geen recht om deze video af te spelen.",
1742
+ ERROR_CODE_VPN_BLOCKED: "VPN GEBLOKKEERD",
1743
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "Deze video is niet beschikbaar vanwege het gebruik van een VPN."
1744
+ };
1745
+
1746
+ // src/messages/fa.json
1747
+ var fa_default = {
1748
+ DAYS: "\u0631\u0648\u0632\u0647\u0627",
1749
+ HOURS: "\u0633\u0627\u0639\u062A\u200C\u0647\u0627",
1750
+ MINUTES: "\u062F\u0642\u06CC\u0642\u0647\u200C\u0647\u0627",
1751
+ SECONDS: "\u062B\u0627\u0646\u06CC\u0647\u200C\u0647\u0627",
1752
+ STARTING_SOON: "\u0628\u0647 \u0632\u0648\u062F\u06CC \u0634\u0631\u0648\u0639 \u0645\u06CC\u200C\u0634\u0648\u062F...",
1753
+ EVENT_NOT_STARTED: "\u0627\u06CC\u0646 \u0631\u0648\u06CC\u062F\u0627\u062F \u0647\u0646\u0648\u0632 \u0634\u0631\u0648\u0639 \u0646\u0634\u062F\u0647 \u0627\u0633\u062A...",
1754
+ DEFAULT_ERROR: "\u062E\u0637\u0627\u06CC \u067E\u062E\u0634",
1755
+ DEFAULT_ERROR_DESCRIPTION: "\u0627\u0645\u06A9\u0627\u0646 \u067E\u062E\u0634 \u0648\u06CC\u062F\u06CC\u0648 \u0648\u062C\u0648\u062F \u0646\u062F\u0627\u0631\u062F. \u0644\u0637\u0641\u0627\u064B \u0628\u0639\u062F\u0627\u064B \u062F\u0648\u0628\u0627\u0631\u0647 \u062A\u0644\u0627\u0634 \u06A9\u0646\u06CC\u062F.",
1756
+ API_ERROR: "\u062E\u0637\u0627 \u062F\u0631 \u0628\u0627\u0632\u06CC\u0627\u0628\u06CC \u0627\u0637\u0644\u0627\u0639\u0627\u062A \u0648\u06CC\u062F\u06CC\u0648",
1757
+ API_ERROR_DESCRIPTION: "\u062E\u0637\u0627 \u062F\u0631 \u062F\u0631\u06CC\u0627\u0641\u062A \u062C\u0632\u0626\u06CC\u0627\u062A \u0648\u06CC\u062F\u06CC\u0648. \u0648\u06CC\u062F\u06CC\u0648Id \u0648 \u0627\u062A\u0635\u0627\u0644 \u0627\u06CC\u0646\u062A\u0631\u0646\u062A \u062E\u0648\u062F \u0631\u0627 \u0628\u0631\u0631\u0633\u06CC \u06A9\u0631\u062F\u0647 \u0648 \u062F\u0648\u0628\u0627\u0631\u0647 \u062A\u0644\u0627\u0634 \u06A9\u0646\u06CC\u062F.",
1758
+ ERROR_CODE_NOT_AUTHENTICATED: "\u0645\u062C\u0648\u0632",
1759
+ ERROR_CODE_NOT_AUTHENTICATED_DESCRIPTION: "\u0634\u0645\u0627 \u0627\u062C\u0627\u0632\u0647 \u067E\u062E\u0634 \u0627\u06CC\u0646 \u0648\u06CC\u062F\u06CC\u0648 \u0631\u0627 \u0646\u062F\u0627\u0631\u06CC\u062F.",
1760
+ ERROR_CODE_GEO_BLOCKED: "\u0645\u062D\u062F\u0648\u062F\u06CC\u062A \u062C\u063A\u0631\u0627\u0641\u06CC\u0627\u06CC\u06CC",
1761
+ ERROR_CODE_GEO_BLOCKED_DESCRIPTION: "\u0645\u062A\u0627\u0633\u0641\u06CC\u0645\u060C \u0627\u06CC\u0646 \u0648\u06CC\u062F\u06CC\u0648 \u0628\u0647 \u062F\u0644\u06CC\u0644 \u0645\u062D\u062F\u0648\u062F\u06CC\u062A\u200C\u0647\u0627\u06CC \u062C\u063A\u0631\u0627\u0641\u06CC\u0627\u06CC\u06CC \u062F\u0631 \u0645\u0646\u0637\u0642\u0647 \u0634\u0645\u0627 \u062F\u0631 \u062F\u0633\u062A\u0631\u0633 \u0646\u06CC\u0633\u062A.",
1762
+ ERROR_CODE_NOT_ENTITLED: "\u0639\u062F\u0645 \u062F\u0633\u062A\u0631\u0633\u06CC",
1763
+ ERROR_CODE_NOT_ENTITLED_DESCRIPTION: "\u0645\u062A\u0627\u0633\u0641\u06CC\u0645\u060C \u0634\u0645\u0627 \u0627\u062C\u0627\u0632\u0647 \u067E\u062E\u0634 \u0627\u06CC\u0646 \u0648\u06CC\u062F\u06CC\u0648 \u0631\u0627 \u0646\u062F\u0627\u0631\u06CC\u062F.",
1764
+ ERROR_CODE_VPN_BLOCKED: "\u0645\u0633\u062F\u0648\u062F \u0634\u062F\u0646 VPN",
1765
+ ERROR_CODE_VPN_BLOCKED_DESCRIPTION: "\u0627\u06CC\u0646 \u0648\u06CC\u062F\u06CC\u0648 \u0628\u0647 \u062F\u0644\u06CC\u0644 \u0627\u0633\u062A\u0641\u0627\u062F\u0647 \u0627\u0632 VPN \u062F\u0631 \u062F\u0633\u062A\u0631\u0633 \u0646\u06CC\u0633\u062A."
1766
+ };
1767
+
1768
+ // src/messages/useMessages.tsx
1769
+ var availableLanguages = {
1770
+ en: en_default,
1771
+ es: es_default,
1772
+ ar: ar_default,
1773
+ de: de_default,
1774
+ fr: fr_default,
1775
+ it: it_default,
1776
+ ja: ja_default,
1777
+ ko: ko_default,
1778
+ pt: pt_default,
1779
+ ru: ru_default,
1780
+ zh: zh_default,
1781
+ nl: nl_default,
1782
+ fa: fa_default
1783
+ };
1784
+ var getBrowserLanguage = () => {
1785
+ const language = navigator.language.split("-")[0];
1786
+ return availableLanguages[language] ? language : "en";
1787
+ };
1788
+ var useMessages = (locale) => {
1789
+ const [language, setLanguage] = useState4("en");
1790
+ const [translations, setTranslations] = useState4(availableLanguages.en);
1791
+ useEffect6(() => {
1792
+ const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
1793
+ ;
1794
+ setLanguage(lang);
1795
+ setTranslations(availableLanguages[lang]);
1796
+ }, [locale]);
1797
+ const t = (key) => {
1798
+ if (translations[key]) {
1799
+ return translations[key];
1800
+ }
1801
+ if (language !== "en" && availableLanguages.en[key]) {
1802
+ return availableLanguages.en[key];
1803
+ }
1804
+ return "";
1805
+ };
1806
+ const changeLanguage = (lng) => {
1807
+ if (availableLanguages[lng]) {
1808
+ setLanguage(lng);
1809
+ setTranslations(availableLanguages[lng]);
1810
+ }
1811
+ };
1812
+ return { t, language, changeLanguage };
1813
+ };
1814
+ var useMessages_default = useMessages;
1815
+
1816
+ // src/Video.tsx
1817
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1818
+ var Video = ({
1819
+ videoId,
1820
+ publicKey,
1821
+ mottoToken,
1822
+ videoData: providedVideoData,
1823
+ refetchInterval = 0,
1824
+ playerName,
1825
+ locale = "en",
1826
+ events,
1827
+ children,
1828
+ className,
1829
+ queryOptions = {},
1830
+ ...props
1831
+ }) => {
1832
+ const {
1833
+ data,
1834
+ isLoading,
1835
+ error,
1836
+ refetch
1837
+ } = useQuery({
1838
+ queryKey: ["video", videoId, publicKey, mottoToken],
1839
+ queryFn: () => fetchVideoData(videoId, publicKey, mottoToken),
1840
+ enabled: !!videoId && !!publicKey && !providedVideoData,
1841
+ refetchInterval: refetchInterval > 0 ? refetchInterval : false,
1842
+ staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
1843
+ // 5 minutes
1844
+ gcTime: queryOptions.cacheTime ?? 10 * 60 * 1e3,
1845
+ // 10 minutes (was cacheTime in v4)
1846
+ retry: queryOptions.retry ?? 3,
1847
+ retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1848
+ });
1849
+ const video = providedVideoData || data;
1850
+ const { t } = useMessages_default(locale);
1851
+ const activePlaylist = findHLSPlaylist(video);
1852
+ const hlsUrl = activePlaylist?.url;
1853
+ useEffect7(() => {
1854
+ if (events?.onVideoData && video) {
1855
+ events.onVideoData(video);
1856
+ }
1857
+ }, [video, events]);
1858
+ if (isLoading || !providedVideoData && !video) {
1859
+ 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, {}) }) });
1860
+ }
1861
+ if (!isLoading && video && !hlsUrl && events?.onEmptyPlaylists) {
1862
+ events.onEmptyPlaylists();
1863
+ }
1864
+ if (error || video?.error) {
1865
+ const errorKey = video?.error ? getErrorType(void 0, video) : "API_ERROR";
1866
+ const errorObj = error || new Error(video?.error || "Unknown error");
1867
+ if (events?.onError) {
1868
+ events.onError(errorObj);
1869
+ }
1870
+ const title = t(errorKey) || t("DEFAULT_ERROR");
1871
+ const description = t(`${errorKey}_DESCRIPTION`) || t("DEFAULT_ERROR_DESCRIPTION");
1872
+ 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: [
1873
+ /* @__PURE__ */ jsx6(
1874
+ ErrorScreen,
1875
+ {
1876
+ title,
1877
+ description
1878
+ }
1879
+ ),
1880
+ children
1881
+ ] }) });
1882
+ }
1883
+ if (!hlsUrl) {
1884
+ 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: [
1885
+ /* @__PURE__ */ jsx6(Title, { title: video?.name || "" }),
1886
+ children
1887
+ ] }) });
1888
+ }
1889
+ console.log("hlsUrl", hlsUrl);
1890
+ 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(
1891
+ Player,
1892
+ {
1893
+ ...props,
1894
+ src: hlsUrl,
1895
+ className: twMerge3("video-player-container", className),
1896
+ events,
1897
+ containerClassName: "w-full h-full",
1898
+ children
1899
+ }
1900
+ ) }) });
1901
+ };
1902
+
1903
+ // src/Event.tsx
1904
+ import { useCallback as useCallback7, useEffect as useEffect8, useState as useState5 } from "react";
1905
+ import { twMerge as twMerge4 } from "tailwind-merge";
1906
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
1907
+ import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1908
+ var Event = ({
1909
+ publicKey,
1910
+ eventId,
1911
+ events,
1912
+ hideTitle,
1913
+ locale = "en",
1914
+ order,
1915
+ filter,
1916
+ className,
1917
+ settings,
1918
+ auth,
1919
+ queryOptions = {},
1920
+ ...props
1921
+ }) => {
1922
+ const {
1923
+ data: eventData,
1924
+ isLoading: isEventLoading,
1925
+ error: eventError
1926
+ } = useQuery2({
1927
+ queryKey: ["event", publicKey, eventId, filter, order, locale],
1928
+ queryFn: () => fetchEventData(publicKey, eventId, void 0, filter, order, locale),
1929
+ enabled: !!publicKey && !!eventId,
1930
+ staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
1931
+ // 5 minutes
1932
+ gcTime: queryOptions.cacheTime ?? 10 * 60 * 1e3,
1933
+ // 10 minutes
1934
+ retry: queryOptions.retry ?? 3,
1935
+ retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1936
+ });
1937
+ const [activePlaylist, setActivePlaylist] = useState5();
1938
+ const [activeVideoId, setActiveVideoId] = useState5();
1939
+ const videoIds = eventData?.videoIds ?? [];
1940
+ const {
1941
+ data: videosData,
1942
+ isLoading: videosIsLoading,
1943
+ error: videosError
1944
+ } = useQuery2({
1945
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
1946
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
1947
+ enabled: !!publicKey && videoIds.length > 0,
1948
+ refetchInterval: activePlaylist === null ? 3e4 : false,
1949
+ staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
1950
+ gcTime: queryOptions.cacheTime ?? 10 * 60 * 1e3,
1951
+ retry: queryOptions.retry ?? 3,
1952
+ retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
1953
+ });
1954
+ const [loadingApisState, setLoadingApisState] = useState5(true);
1955
+ useEffect8(() => {
1956
+ if (videosData !== void 0) {
1957
+ setLoadingApisState(false);
1958
+ const videosWithPlaylists = videosData.filter(
1959
+ (video) => video.playlists && video.playlists.length > 0
1960
+ );
1961
+ if (videosWithPlaylists.length > 0) {
1962
+ let hlsPlaylistFound = false;
1963
+ for (const video of videosWithPlaylists) {
1964
+ const hlsPlaylist = findHLSPlaylist(video);
1965
+ if (hlsPlaylist?.url) {
1966
+ setActivePlaylist(hlsPlaylist.url);
1967
+ setActiveVideoId(video.id);
1968
+ hlsPlaylistFound = true;
1969
+ break;
1970
+ }
1971
+ }
1972
+ if (!hlsPlaylistFound) {
1973
+ setActivePlaylist(null);
1974
+ setActiveVideoId(null);
1975
+ }
1976
+ } else {
1977
+ setActivePlaylist(null);
1978
+ setActiveVideoId(null);
1979
+ }
1980
+ } else if (eventData && (!eventData.videoIds || eventData.videoIds.length === 0)) {
1981
+ setLoadingApisState(false);
1982
+ setActivePlaylist(null);
1983
+ setActiveVideoId(null);
1984
+ }
1985
+ }, [videosData, eventData]);
1986
+ const { t } = useMessages_default(locale);
1987
+ useEffect8(() => {
1988
+ if (events?.onEventData && eventData) {
1989
+ events.onEventData(eventData);
1990
+ }
1991
+ }, [eventData, events]);
1992
+ useEffect8(() => {
1993
+ if (events?.onVideoData && activeVideoId && videosData) {
1994
+ const activeVideo = videosData.find((video) => video.id === activeVideoId);
1995
+ if (activeVideo) {
1996
+ events.onVideoData(activeVideo);
1997
+ }
1998
+ }
1999
+ }, [activeVideoId, videosData, events]);
2000
+ const [error, setError] = useState5(null);
2001
+ const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
2002
+ const videosDataError = videosData?.some((video) => !!video.error);
2003
+ useEffect8(() => {
2004
+ if (eventError || videosError || videosDataError) {
2005
+ const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
2006
+ setError(errorObj);
2007
+ if (events?.onError) {
2008
+ events.onError(errorObj);
2009
+ }
2010
+ } else {
2011
+ setError(null);
2012
+ }
2013
+ }, [eventError, videosError, videosDataError, videosData, events]);
2014
+ useEffect8(() => {
2015
+ const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
2016
+ const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
2017
+ if (eventLoadedWithNoVideos || allApisLoadedWithPotentialVideos) {
2018
+ setLoadingPlaylist(false);
2019
+ }
2020
+ }, [isEventLoading, videosIsLoading, eventData, loadingApisState]);
2021
+ if (error) {
2022
+ const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
2023
+ const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
2024
+ 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(
2025
+ ErrorScreen,
2026
+ {
2027
+ title,
2028
+ description
2029
+ }
2030
+ ) }) });
2031
+ }
2032
+ if (!loadingPlaylist && eventData && !activePlaylist && events?.onEmptyPlaylists) {
2033
+ events.onEmptyPlaylists();
2034
+ }
2035
+ if (loadingPlaylist) {
2036
+ 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, {}) }) });
2037
+ }
2038
+ if (activePlaylist && activeVideoId && videosData) {
2039
+ const activeVideo = videosData.find((video) => video.id === activeVideoId);
2040
+ 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: [
2041
+ /* @__PURE__ */ jsx7(
2042
+ Player,
2043
+ {
2044
+ ...props,
2045
+ src: activePlaylist,
2046
+ className: twMerge4(className, "peer"),
2047
+ events,
2048
+ containerClassName: "w-full h-full"
2049
+ }
2050
+ ),
2051
+ !hideTitle && eventData && /* @__PURE__ */ jsx7(
2052
+ TitleAndDescription,
2053
+ {
2054
+ title: eventData.title,
2055
+ description: eventData.description || "",
2056
+ startTime: eventData.startTime,
2057
+ locale
2058
+ }
2059
+ )
2060
+ ] }) });
2061
+ }
2062
+ if (eventData) {
2063
+ 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(
2064
+ PreEvent,
2065
+ {
2066
+ event: eventData,
2067
+ hideTitle,
2068
+ locale,
2069
+ backgroundImageUrl: settings?.backgroundImageUrl,
2070
+ showAnimation: settings?.showCountdownAnimation
2071
+ }
2072
+ ) }) });
2073
+ }
2074
+ return null;
2075
+ };
2076
+ function PreEvent({
2077
+ event,
2078
+ locale = "en",
2079
+ hideTitle,
2080
+ backgroundImageUrl,
2081
+ showAnimation = true
2082
+ }) {
2083
+ const date = new Date(event.startTime);
2084
+ const now = /* @__PURE__ */ new Date();
2085
+ const [remainingTime, setRemainingTime] = useState5(
2086
+ date.getTime() - now.getTime()
2087
+ );
2088
+ const shouldBeStarted = remainingTime < 0;
2089
+ const { t } = useMessages_default(locale);
2090
+ useEffect8(() => {
2091
+ const interval = setInterval(() => {
2092
+ if (remainingTime < 0) {
2093
+ clearInterval(interval);
2094
+ } else {
2095
+ setRemainingTime(date.getTime() - (/* @__PURE__ */ new Date()).getTime());
2096
+ }
2097
+ }, 1e3);
2098
+ return () => clearInterval(interval);
2099
+ }, [date, remainingTime]);
2100
+ const renderCountdown = useCallback7(() => {
2101
+ if (shouldBeStarted) {
2102
+ return /* @__PURE__ */ jsx7("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
2103
+ }
2104
+ const seconds = Math.floor(remainingTime / 1e3) % 60;
2105
+ const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
2106
+ const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
2107
+ const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
2108
+ return /* @__PURE__ */ jsxs6("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
2109
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2110
+ /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
2111
+ "span",
2112
+ {
2113
+ style: { "--value": days },
2114
+ "aria-live": "polite",
2115
+ "aria-label": days.toString(),
2116
+ children: days?.toString()?.padStart(2, "0")
2117
+ }
2118
+ ) }),
2119
+ /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
2120
+ ] }),
2121
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2122
+ /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
2123
+ "span",
2124
+ {
2125
+ style: { "--value": hours },
2126
+ "aria-live": "polite",
2127
+ "aria-label": hours.toString(),
2128
+ children: hours?.toString()?.padStart(2, "0")
2129
+ }
2130
+ ) }),
2131
+ /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
2132
+ ] }),
2133
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2134
+ /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
2135
+ "span",
2136
+ {
2137
+ style: { "--value": minutes },
2138
+ "aria-live": "polite",
2139
+ "aria-label": minutes.toString(),
2140
+ children: minutes?.toString()?.padStart(2, "0")
2141
+ }
2142
+ ) }),
2143
+ /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
2144
+ ] }),
2145
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2146
+ /* @__PURE__ */ jsx7("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx7(
2147
+ "span",
2148
+ {
2149
+ style: { "--value": seconds },
2150
+ "aria-live": "polite",
2151
+ "aria-label": seconds.toString(),
2152
+ children: seconds?.toString()?.padStart(2, "0")
2153
+ }
2154
+ ) }),
2155
+ /* @__PURE__ */ jsx7("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
2156
+ ] })
2157
+ ] });
2158
+ }, [remainingTime, shouldBeStarted, t]);
2159
+ return /* @__PURE__ */ jsx7(Fragment, { children: event?.posterUrl ? /* @__PURE__ */ jsxs6(Fragment, { children: [
2160
+ /* @__PURE__ */ jsxs6(
2161
+ "div",
2162
+ {
2163
+ 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",
2164
+ style: {
2165
+ backgroundImage: `url(${event.posterUrl})`,
2166
+ backgroundRepeat: "no-repeat",
2167
+ backgroundSize: "cover"
2168
+ },
2169
+ children: [
2170
+ /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
2171
+ /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
2172
+ ]
2173
+ }
2174
+ ),
2175
+ !hideTitle && /* @__PURE__ */ jsx7(
2176
+ TitleAndDescription,
2177
+ {
2178
+ title: event.title,
2179
+ description: event.description || "",
2180
+ startTime: event.startTime,
2181
+ locale
2182
+ }
2183
+ )
2184
+ ] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
2185
+ /* @__PURE__ */ jsxs6(
2186
+ "div",
2187
+ {
2188
+ 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",
2189
+ style: {
2190
+ backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
2191
+ },
2192
+ children: [
2193
+ backgroundImageUrl && /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
2194
+ /* @__PURE__ */ jsx7("div", { className: "relative z-10", children: renderCountdown() })
2195
+ ]
2196
+ }
2197
+ ),
2198
+ !hideTitle && /* @__PURE__ */ jsx7(
2199
+ TitleAndDescription,
2200
+ {
2201
+ title: event.title,
2202
+ description: event.description || "",
2203
+ startTime: event.startTime,
2204
+ locale
2205
+ }
2206
+ )
2207
+ ] }) });
2208
+ }
2209
+ var TitleAndDescription = ({
2210
+ title,
2211
+ description,
2212
+ startTime,
2213
+ locale = "en",
2214
+ className
2215
+ }) => {
2216
+ return /* @__PURE__ */ jsxs6("div", { className: twMerge4("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
2217
+ /* @__PURE__ */ jsx7("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
2218
+ startTime ? /* @__PURE__ */ jsxs6("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
2219
+ new Date(startTime || "").toLocaleDateString(locale || "default", {
2220
+ month: "long",
2221
+ year: "numeric",
2222
+ day: "numeric"
2223
+ }),
2224
+ " ",
2225
+ "- ",
2226
+ new Date(startTime || "").toLocaleTimeString(locale || "default", {
2227
+ hour: "2-digit",
2228
+ minute: "2-digit"
2229
+ })
2230
+ ] }) : null,
2231
+ description && /* @__PURE__ */ jsx7("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
2232
+ ] });
2233
+ };
2234
+
2235
+ // src/CreativeWork.tsx
2236
+ import { useEffect as useEffect9, useState as useState6 } from "react";
2237
+ import { twMerge as twMerge5 } from "tailwind-merge";
2238
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
2239
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2240
+ var CreativeWork = ({
2241
+ publicKey,
2242
+ creativeWorkId,
2243
+ events,
2244
+ hideTitle,
2245
+ locale = "en",
2246
+ order,
2247
+ filter,
2248
+ className,
2249
+ settings,
2250
+ auth,
2251
+ queryOptions = {},
2252
+ ...props
2253
+ }) => {
2254
+ const {
2255
+ data: creativeWorkData,
2256
+ isLoading: isCreativeWorkLoading,
2257
+ error: creativeWorkError
2258
+ } = useQuery3({
2259
+ queryKey: ["creative-work", publicKey, creativeWorkId, filter, order, locale],
2260
+ queryFn: () => fetchCreativeWorkData(publicKey, creativeWorkId, void 0, filter, order, locale),
2261
+ enabled: !!publicKey && !!creativeWorkId,
2262
+ staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
2263
+ // 5 minutes
2264
+ gcTime: queryOptions.cacheTime ?? 10 * 60 * 1e3,
2265
+ // 10 minutes
2266
+ retry: queryOptions.retry ?? 3,
2267
+ retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2268
+ });
2269
+ const [activePlaylist, setActivePlaylist] = useState6();
2270
+ const [activeVideoId, setActiveVideoId] = useState6();
2271
+ const [showCountDown, setShowCountDown] = useState6(false);
2272
+ const videoIds = creativeWorkData?.videoIds ?? [];
2273
+ const {
2274
+ data: videosData,
2275
+ isLoading: videosIsLoading,
2276
+ error: videosError
2277
+ } = useQuery3({
2278
+ queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
2279
+ queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
2280
+ enabled: !!publicKey && videoIds.length > 0,
2281
+ refetchInterval: activePlaylist === null ? 3e4 : false,
2282
+ staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
2283
+ gcTime: queryOptions.cacheTime ?? 10 * 60 * 1e3,
2284
+ retry: queryOptions.retry ?? 3,
2285
+ retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
2286
+ });
2287
+ const [loadingApisState, setLoadingApisState] = useState6(true);
2288
+ useEffect9(() => {
2289
+ if (videosData !== void 0) {
2290
+ setLoadingApisState(false);
2291
+ const videosWithPlaylists = videosData.filter(
2292
+ (video) => video.playlists && video.playlists.length > 0
2293
+ );
2294
+ if (videosWithPlaylists.length > 0) {
2295
+ let hlsPlaylistFound = false;
2296
+ for (const video of videosWithPlaylists) {
2297
+ const hlsPlaylist = findHLSPlaylist(video);
2298
+ if (hlsPlaylist?.url) {
2299
+ setActivePlaylist(hlsPlaylist.url);
2300
+ setActiveVideoId(video.id);
2301
+ hlsPlaylistFound = true;
2302
+ break;
2303
+ }
2304
+ }
2305
+ if (!hlsPlaylistFound) {
2306
+ setActivePlaylist(null);
2307
+ setActiveVideoId(null);
2308
+ }
2309
+ } else {
2310
+ setActivePlaylist(null);
2311
+ setActiveVideoId(null);
2312
+ }
2313
+ } else if (creativeWorkData && (!creativeWorkData.videoIds || creativeWorkData.videoIds.length === 0)) {
2314
+ setLoadingApisState(false);
2315
+ setActivePlaylist(null);
2316
+ setActiveVideoId(null);
2317
+ }
2318
+ }, [videosData, creativeWorkData]);
2319
+ const { t } = useMessages_default(locale);
2320
+ useEffect9(() => {
2321
+ if (events?.onCreativeWorkData && creativeWorkData) {
2322
+ events.onCreativeWorkData(creativeWorkData);
2323
+ }
2324
+ if (creativeWorkData && !creativeWorkData?.videoIds?.length) {
2325
+ setShowCountDown(true);
2326
+ }
2327
+ }, [creativeWorkData, events]);
2328
+ useEffect9(() => {
2329
+ if (events?.onVideoData && activeVideoId && videosData) {
2330
+ const activeVideo = videosData.find((video) => video.id === activeVideoId);
2331
+ if (activeVideo) {
2332
+ events.onVideoData(activeVideo);
2333
+ }
2334
+ }
2335
+ }, [activeVideoId, videosData, events]);
2336
+ const [error, setError] = useState6(null);
2337
+ const videosDataError = videosData?.some((video) => !!video.error);
2338
+ useEffect9(() => {
2339
+ if (creativeWorkError || videosError || videosDataError) {
2340
+ const errorObj = creativeWorkError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
2341
+ setError(errorObj);
2342
+ if (events?.onError) {
2343
+ events.onError(errorObj);
2344
+ }
2345
+ } else {
2346
+ setError(null);
2347
+ }
2348
+ }, [creativeWorkError, videosError, videosDataError, videosData, events]);
2349
+ if (error) {
2350
+ const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
2351
+ const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
2352
+ 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(
2353
+ ErrorScreen,
2354
+ {
2355
+ title,
2356
+ description
2357
+ }
2358
+ ) }) });
2359
+ }
2360
+ const [loadingPlaylist, setLoadingPlaylist] = useState6(true);
2361
+ useEffect9(() => {
2362
+ const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
2363
+ const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
2364
+ const isEventsFinished = !videosIsLoading && videosData && videosData.length > 0 && videosData.every((video) => video.playlists && video.playlists.length === 0);
2365
+ if (creativeWorkLoadedWithNoVideos || creativeWorkLoadedWithNoData || isEventsFinished) {
2366
+ setLoadingPlaylist(false);
2367
+ if (events?.onEmptyPlaylists) {
2368
+ events.onEmptyPlaylists();
2369
+ }
2370
+ } else if (activePlaylist) {
2371
+ setLoadingPlaylist(false);
2372
+ }
2373
+ }, [
2374
+ isCreativeWorkLoading,
2375
+ creativeWorkData,
2376
+ videosIsLoading,
2377
+ videosData,
2378
+ activePlaylist,
2379
+ events
2380
+ ]);
2381
+ if (isCreativeWorkLoading || videosIsLoading || loadingApisState) {
2382
+ 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, {}) }) });
2383
+ }
2384
+ if (showCountDown && creativeWorkData) {
2385
+ 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(
2386
+ PreCreativeWork,
2387
+ {
2388
+ creativeWork: creativeWorkData,
2389
+ locale,
2390
+ hideTitle,
2391
+ backgroundImageUrl: settings?.backgroundImageUrl,
2392
+ showAnimation: settings?.showCountdownAnimation
2393
+ }
2394
+ ) }) });
2395
+ }
2396
+ if (activeVideoId && activePlaylist && !loadingPlaylist) {
2397
+ const activeVideo = videosData?.find((video) => video.id === activeVideoId);
2398
+ 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: [
2399
+ /* @__PURE__ */ jsx8(
2400
+ Player,
2401
+ {
2402
+ ...props,
2403
+ className: twMerge5(className, "peer"),
2404
+ events: {
2405
+ ...events
2406
+ },
2407
+ src: activePlaylist,
2408
+ containerClassName: "w-full h-full"
2409
+ }
2410
+ ),
2411
+ !hideTitle && /* @__PURE__ */ jsx8(
2412
+ TitleAndDescription2,
2413
+ {
2414
+ title: creativeWorkData?.title || "",
2415
+ description: creativeWorkData?.description || "",
2416
+ releaseTime: creativeWorkData?.releaseTime || "",
2417
+ locale,
2418
+ className: "mt-3 mb-6 m-event-details-ctn px-4"
2419
+ }
2420
+ )
2421
+ ] }) });
2422
+ }
2423
+ if (loadingPlaylist) {
2424
+ return /* @__PURE__ */ jsx8(Loading, {});
2425
+ }
2426
+ return null;
2427
+ };
2428
+ function PreCreativeWork({
2429
+ creativeWork,
2430
+ locale = "en",
2431
+ hideTitle,
2432
+ backgroundImageUrl,
2433
+ showAnimation = true
2434
+ }) {
2435
+ const date = new Date(creativeWork.releaseTime);
2436
+ const now = /* @__PURE__ */ new Date();
2437
+ const [remainingTime, setRemainingTime] = useState6(
2438
+ date.getTime() - now.getTime()
2439
+ );
2440
+ const shouldBeStarted = remainingTime < 0;
2441
+ const { t } = useMessages_default(locale);
2442
+ useEffect9(() => {
2443
+ const interval = setInterval(() => {
2444
+ if (remainingTime < 0) {
2445
+ clearInterval(interval);
2446
+ } else {
2447
+ setRemainingTime(date.getTime() - (/* @__PURE__ */ new Date()).getTime());
2448
+ }
2449
+ }, 1e3);
2450
+ return () => {
2451
+ clearInterval(interval);
2452
+ };
2453
+ }, [date, remainingTime]);
2454
+ const renderCountdown = () => {
2455
+ if (shouldBeStarted) {
2456
+ return /* @__PURE__ */ jsx8("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
2457
+ }
2458
+ const seconds = Math.floor(remainingTime / 1e3) % 60;
2459
+ const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
2460
+ const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
2461
+ const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
2462
+ return /* @__PURE__ */ jsxs7("div", { className: "grid grid-flow-col gap-5 text-center auto-cols-max", children: [
2463
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2464
+ /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
2465
+ "span",
2466
+ {
2467
+ style: { "--value": days },
2468
+ "aria-live": "polite",
2469
+ "aria-label": days.toString(),
2470
+ children: days?.toString()?.padStart(2, "0")
2471
+ }
2472
+ ) }),
2473
+ /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("DAYS") })
2474
+ ] }),
2475
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2476
+ /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
2477
+ "span",
2478
+ {
2479
+ style: { "--value": hours },
2480
+ "aria-live": "polite",
2481
+ "aria-label": hours.toString(),
2482
+ children: hours?.toString()?.padStart(2, "0")
2483
+ }
2484
+ ) }),
2485
+ /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("HOURS") })
2486
+ ] }),
2487
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2488
+ /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
2489
+ "span",
2490
+ {
2491
+ style: { "--value": minutes },
2492
+ "aria-live": "polite",
2493
+ "aria-label": minutes.toString(),
2494
+ children: minutes?.toString()?.padStart(2, "0")
2495
+ }
2496
+ ) }),
2497
+ /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("MINUTES") })
2498
+ ] }),
2499
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
2500
+ /* @__PURE__ */ jsx8("span", { className: "countdown font-mono text-5xl", children: /* @__PURE__ */ jsx8(
2501
+ "span",
2502
+ {
2503
+ style: { "--value": seconds },
2504
+ "aria-live": "polite",
2505
+ "aria-label": seconds.toString(),
2506
+ children: seconds?.toString()?.padStart(2, "0")
2507
+ }
2508
+ ) }),
2509
+ /* @__PURE__ */ jsx8("span", { className: "text-sm uppercase tracking-widest mt-1", children: t("SECONDS") })
2510
+ ] })
2511
+ ] });
2512
+ };
2513
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
2514
+ /* @__PURE__ */ jsxs7(
2515
+ "div",
2516
+ {
2517
+ 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",
2518
+ style: {
2519
+ backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
2520
+ },
2521
+ children: [
2522
+ backgroundImageUrl && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
2523
+ /* @__PURE__ */ jsx8("div", { className: "relative z-10", children: renderCountdown() })
2524
+ ]
2525
+ }
2526
+ ),
2527
+ !hideTitle && /* @__PURE__ */ jsx8(
2528
+ TitleAndDescription2,
2529
+ {
2530
+ title: creativeWork.title,
2531
+ description: creativeWork.description || "",
2532
+ releaseTime: creativeWork.releaseTime,
2533
+ locale
2534
+ }
2535
+ )
2536
+ ] });
2537
+ }
2538
+ var TitleAndDescription2 = ({
2539
+ title,
2540
+ description,
2541
+ releaseTime,
2542
+ locale = "en",
2543
+ className
2544
+ }) => {
2545
+ return /* @__PURE__ */ jsxs7("div", { className: twMerge5("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
2546
+ /* @__PURE__ */ jsx8("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
2547
+ releaseTime ? /* @__PURE__ */ jsxs7("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
2548
+ new Date(releaseTime || "").toLocaleDateString(locale || "default", {
2549
+ month: "long",
2550
+ year: "numeric",
2551
+ day: "numeric"
2552
+ }),
2553
+ " ",
2554
+ "- ",
2555
+ new Date(releaseTime || "").toLocaleTimeString(locale || "default", {
2556
+ hour: "2-digit",
2557
+ minute: "2-digit"
2558
+ })
2559
+ ] }) : null,
2560
+ description && /* @__PURE__ */ jsx8("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
2561
+ ] });
2562
+ };
2563
+
2564
+ // src/QueryProvider.tsx
2565
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2566
+ import { jsx as jsx9 } from "react/jsx-runtime";
2567
+ var queryClient = new QueryClient({
2568
+ defaultOptions: {
2569
+ queries: {
2570
+ staleTime: 5 * 60 * 1e3,
2571
+ // 5 minutes
2572
+ gcTime: 10 * 60 * 1e3,
2573
+ // 10 minutes
2574
+ retry: 3,
2575
+ refetchOnWindowFocus: false
2576
+ }
2577
+ }
2578
+ });
2579
+ var QueryProvider = ({ children }) => {
2580
+ return /* @__PURE__ */ jsx9(QueryClientProvider, { client: queryClient, children });
2581
+ };
2582
+ export {
2583
+ CreativeWork,
2584
+ Event,
2585
+ Player,
2586
+ QueryProvider,
2587
+ Video,
2588
+ queryClient
2589
+ };
2590
+ //# sourceMappingURL=index.mjs.map