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