@zezosoft/react-player 0.0.5 → 0.0.7

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.
Files changed (31) hide show
  1. package/dist/VideoPlayer/VideoPlayer.d.ts +4 -40
  2. package/dist/VideoPlayer/_components/SubtitleOverlay.d.ts +7 -0
  3. package/dist/VideoPlayer/hooks/index.d.ts +7 -0
  4. package/dist/VideoPlayer/hooks/useEpisodes.d.ts +3 -0
  5. package/dist/VideoPlayer/hooks/useIntroSkip.d.ts +5 -0
  6. package/dist/VideoPlayer/hooks/useSubtitleStyling.d.ts +10 -0
  7. package/dist/VideoPlayer/hooks/useSubtitles.d.ts +2 -0
  8. package/dist/VideoPlayer/hooks/useVideoEvents.d.ts +10 -0
  9. package/dist/VideoPlayer/hooks/useVideoSource.d.ts +1 -0
  10. package/dist/VideoPlayer/hooks/useVideoTracking.d.ts +2 -0
  11. package/dist/VideoPlayer/types/VideoPlayerTypes.d.ts +49 -0
  12. package/dist/VideoPlayer/utils/index.d.ts +6 -6
  13. package/dist/components/ui/Popover.d.ts +2 -0
  14. package/dist/components/ui/Settings.d.ts +6 -0
  15. package/dist/components/ui/tooltip.d.ts +1 -1
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.js +660 -252
  18. package/dist/store/VideoState.d.ts +1 -73
  19. package/dist/store/index.d.ts +3 -0
  20. package/dist/store/slices/episodesSlice.d.ts +5 -0
  21. package/dist/store/slices/index.d.ts +9 -0
  22. package/dist/store/slices/introSlice.d.ts +5 -0
  23. package/dist/store/slices/resetSlice.d.ts +5 -0
  24. package/dist/store/slices/subtitlesSlice.d.ts +5 -0
  25. package/dist/store/slices/videoControlsSlice.d.ts +5 -0
  26. package/dist/store/slices/videoPlaybackSlice.d.ts +5 -0
  27. package/dist/store/slices/videoQualitySlice.d.ts +5 -0
  28. package/dist/store/slices/videoRefsSlice.d.ts +5 -0
  29. package/dist/store/slices/videoTimingSlice.d.ts +5 -0
  30. package/dist/store/types/StoreTypes.d.ts +78 -0
  31. package/package.json +10 -8
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { memo, useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { create } from 'zustand';
4
- import { FaCheck, FaGooglePlay } from 'react-icons/fa';
5
4
  import { IoVolumeMuteOutline, IoVolumeHighOutline } from 'react-icons/io5';
6
- import { Settings, Loader } from 'lucide-react';
7
5
  import { IoMdClose } from 'react-icons/io';
6
+ import { Settings as Settings$1, ChevronRight, Check, Loader, ArrowRight } from 'lucide-react';
7
+ import screenfull from 'screenfull';
8
8
  import Hls from 'hls.js';
9
9
 
10
10
  function styleInject(css, ref) {
@@ -34,14 +34,17 @@ function styleInject(css, ref) {
34
34
  }
35
35
  }
36
36
 
37
- var css_248z$2 = "/*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-green-100: oklch(96.2% 0.044 156.743);\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-gray-50: oklch(98.5% 0.002 247.839);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\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-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --font-weight-normal: 400;\n --font-weight-semibold: 600;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --animate-spin: spin 1s linear infinite;\n --blur-sm: 8px;\n --blur-md: 12px;\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 *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :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, h2, h3, h4, h5, 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, strong {\n font-weight: bolder;\n }\n code, kbd, samp, 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, 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, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::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, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-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-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .-top-2 {\n top: calc(var(--spacing) * -2);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .top-full {\n top: 100%;\n }\n .right-32 {\n right: calc(var(--spacing) * 32);\n }\n .right-full {\n right: 100%;\n }\n .bottom-36 {\n bottom: calc(var(--spacing) * 36);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .left-32 {\n left: calc(var(--spacing) * 32);\n }\n .left-full {\n left: 100%;\n }\n .z-50 {\n z-index: 50;\n }\n .z-\\[-1\\] {\n z-index: -1;\n }\n .mx-2 {\n margin-inline: calc(var(--spacing) * 2);\n }\n .mx-auto {\n margin-inline: auto;\n }\n .mt-2 {\n margin-top: calc(var(--spacing) * 2);\n }\n .mr-2 {\n margin-right: calc(var(--spacing) * 2);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .ml-2 {\n margin-left: calc(var(--spacing) * 2);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .h-3 {\n height: calc(var(--spacing) * 3);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-10 {\n height: calc(var(--spacing) * 10);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-3 {\n width: calc(var(--spacing) * 3);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-56 {\n width: calc(var(--spacing) * 56);\n }\n .w-\\[2px\\] {\n width: 2px;\n }\n .w-\\[10vw\\] {\n width: 10vw;\n }\n .w-\\[15vw\\] {\n width: 15vw;\n }\n .w-\\[720px\\] {\n width: 720px;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .rotate-45 {\n rotate: 45deg;\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-not-allowed {\n cursor: not-allowed;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .gap-7 {\n gap: calc(var(--spacing) * 7);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .border-gray-200 {\n border-color: var(--color-gray-200);\n }\n .bg-\\[rgba\\(0\\,0\\,0\\,0\\.5\\)\\] {\n background-color: rgba(0,0,0,0.5);\n }\n .bg-gray-500 {\n background-color: var(--color-gray-500);\n }\n .bg-gray-900 {\n background-color: var(--color-gray-900);\n }\n .bg-green-100 {\n background-color: var(--color-green-100);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-white\\/80 {\n background-color: color-mix(in srgb, #fff 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 80%, transparent);\n }\n }\n .bg-white\\/90 {\n background-color: color-mix(in srgb, #fff 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 90%, transparent);\n }\n }\n .bg-gradient-to-b {\n --tw-gradient-position: to bottom in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black {\n --tw-gradient-from: var(--color-black);\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 .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-10 {\n padding: calc(var(--spacing) * 10);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .px-10 {\n padding-inline: calc(var(--spacing) * 10);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .pt-6 {\n padding-top: calc(var(--spacing) * 6);\n }\n .pb-10 {\n padding-bottom: calc(var(--spacing) * 10);\n }\n .pb-16 {\n padding-bottom: calc(var(--spacing) * 16);\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 .font-normal {\n --tw-font-weight: var(--font-weight-normal);\n font-weight: var(--font-weight-normal);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-black {\n color: var(--color-black);\n }\n .text-gray-200 {\n color: var(--color-gray-200);\n }\n .text-gray-300 {\n color: var(--color-gray-300);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-700 {\n color: var(--color-gray-700);\n }\n .text-gray-900 {\n color: var(--color-gray-900);\n }\n .text-green-500 {\n color: var(--color-green-500);\n }\n .text-white {\n color: var(--color-white);\n }\n .opacity-50 {\n opacity: 50%;\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: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-md {\n --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .backdrop-blur-md {\n --tw-backdrop-blur: blur(var(--blur-md));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .backdrop-blur-sm {\n --tw-backdrop-blur: blur(var(--blur-sm));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .transition {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-all {\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 }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\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 }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .ease-in-out {\n --tw-ease: var(--ease-in-out);\n transition-timing-function: var(--ease-in-out);\n }\n .hover\\:bg-gray-200 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-200);\n }\n }\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-white\\/90 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 90%, transparent);\n }\n }\n }\n }\n .hover\\:text-gray-200 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-gray-400 {\n &:focus {\n --tw-ring-color: var(--color-gray-400);\n }\n }\n .focus\\:ring-offset-1 {\n &:focus {\n --tw-ring-offset-width: 1px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .disabled\\:cursor-not-allowed {\n &:disabled {\n cursor: not-allowed;\n }\n }\n .disabled\\:bg-white\\/50 {\n &:disabled {\n background-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n .disabled\\:opacity-50 {\n &:disabled {\n opacity: 50%;\n }\n }\n .lg\\:h-32 {\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 32);\n }\n }\n .lg\\:w-32 {\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 32);\n }\n }\n .lg\\:pb-12 {\n @media (width >= 64rem) {\n padding-bottom: calc(var(--spacing) * 12);\n }\n }\n .lg\\:text-2xl {\n @media (width >= 64rem) {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n }\n .lg\\:text-3xl {\n @media (width >= 64rem) {\n font-size: var(--text-3xl);\n line-height: var(--tw-leading, var(--text-3xl--line-height));\n }\n }\n .lg\\:text-base {\n @media (width >= 64rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .\\[\\&\\:\\:cue\\]\\:absolute {\n &::cue {\n position: absolute;\n }\n }\n .\\[\\&\\:\\:cue\\]\\:top-\\[6\\%\\] {\n &::cue {\n top: 6%;\n }\n }\n .\\[\\&\\:\\:cue\\]\\:rounded-md {\n &::cue {\n border-radius: var(--radius-md);\n }\n }\n .\\[\\&\\:\\:cue\\]\\:bg-gray-50 {\n &::cue {\n background-color: var(--color-gray-50);\n }\n }\n .\\[\\&\\:\\:cue\\]\\:px-2 {\n &::cue {\n padding-inline: calc(var(--spacing) * 2);\n }\n }\n .\\[\\&\\:\\:cue\\]\\:py-1 {\n &::cue {\n padding-block: calc(var(--spacing) * 1);\n }\n }\n .\\[\\&\\:\\:cue\\]\\:text-xl {\n &::cue {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n .\\[\\&\\:\\:cue\\]\\:text-\\[\\#1E1E1E\\] {\n &::cue {\n color: #1E1E1E;\n }\n }\n}\n.noCursor {\n cursor: none !important;\n}\n.icon-class {\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n color: var(--color-gray-400);\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\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 color: var(--color-gray-200);\n }\n }\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-gradient-position {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-via {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-to {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-via-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 0%;\n}\n@property --tw-gradient-via-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 50%;\n}\n@property --tw-gradient-to-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\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 *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\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-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-backdrop-blur: initial;\n --tw-backdrop-brightness: initial;\n --tw-backdrop-contrast: initial;\n --tw-backdrop-grayscale: initial;\n --tw-backdrop-hue-rotate: initial;\n --tw-backdrop-invert: initial;\n --tw-backdrop-opacity: initial;\n --tw-backdrop-saturate: initial;\n --tw-backdrop-sepia: initial;\n --tw-duration: initial;\n --tw-ease: initial;\n }\n }\n}\n";
38
- styleInject(css_248z$2,{"insertAt":"top"});
37
+ var css_248z$3 = "/*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-purple-500: oklch(62.7% 0.265 303.9);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\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-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --font-weight-normal: 400;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --animate-spin: spin 1s linear infinite;\n --blur-sm: 8px;\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 *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :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, h2, h3, h4, h5, 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, strong {\n font-weight: bolder;\n }\n code, kbd, samp, 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, 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, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::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, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-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-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .-top-2 {\n top: calc(var(--spacing) * -2);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .top-full {\n top: 100%;\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-32 {\n right: calc(var(--spacing) * 32);\n }\n .right-full {\n right: 100%;\n }\n .bottom-36 {\n bottom: calc(var(--spacing) * 36);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-32 {\n left: calc(var(--spacing) * 32);\n }\n .left-full {\n left: 100%;\n }\n .z-50 {\n z-index: 50;\n }\n .z-\\[-1\\] {\n z-index: -1;\n }\n .mx-2 {\n margin-inline: calc(var(--spacing) * 2);\n }\n .mx-auto {\n margin-inline: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-2 {\n margin-top: calc(var(--spacing) * 2);\n }\n .mr-2 {\n margin-right: calc(var(--spacing) * 2);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .ml-2 {\n margin-left: calc(var(--spacing) * 2);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .hidden {\n display: none;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .h-3 {\n height: calc(var(--spacing) * 3);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-6 {\n height: calc(var(--spacing) * 6);\n }\n .h-10 {\n height: calc(var(--spacing) * 10);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .max-h-80 {\n max-height: calc(var(--spacing) * 80);\n }\n .w-3 {\n width: calc(var(--spacing) * 3);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-6 {\n width: calc(var(--spacing) * 6);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-80 {\n width: calc(var(--spacing) * 80);\n }\n .w-\\[2px\\] {\n width: 2px;\n }\n .w-\\[10vw\\] {\n width: 10vw;\n }\n .w-\\[15vw\\] {\n width: 15vw;\n }\n .w-\\[720px\\] {\n width: 720px;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .rotate-45 {\n rotate: 45deg;\n }\n .rotate-180 {\n rotate: 180deg;\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-not-allowed {\n cursor: not-allowed;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .gap-3 {\n gap: calc(var(--spacing) * 3);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .gap-7 {\n gap: calc(var(--spacing) * 7);\n }\n .space-y-0 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-3 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-\\[5px\\] {\n border-radius: 5px;\n }\n .rounded-\\[7px\\] {\n border-radius: 7px;\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 1px;\n }\n .border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .border-gray-600 {\n border-color: var(--color-gray-600);\n }\n .border-white\\/10 {\n border-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .bg-\\[\\#3a4049\\] {\n background-color: #3a4049;\n }\n .bg-\\[\\#454545\\] {\n background-color: #454545;\n }\n .bg-\\[rgba\\(0\\,0\\,0\\,0\\.5\\)\\] {\n background-color: rgba(0,0,0,0.5);\n }\n .bg-blue-500 {\n background-color: var(--color-blue-500);\n }\n .bg-gray-500 {\n background-color: var(--color-gray-500);\n }\n .bg-gray-900 {\n background-color: var(--color-gray-900);\n }\n .bg-green-500 {\n background-color: var(--color-green-500);\n }\n .bg-purple-500 {\n background-color: var(--color-purple-500);\n }\n .bg-white\\/10 {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .bg-white\\/80 {\n background-color: color-mix(in srgb, #fff 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 80%, transparent);\n }\n }\n .bg-gradient-to-b {\n --tw-gradient-position: to bottom in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black {\n --tw-gradient-from: var(--color-black);\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 .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-10 {\n padding: calc(var(--spacing) * 10);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .px-10 {\n padding-inline: calc(var(--spacing) * 10);\n }\n .px-20 {\n padding-inline: calc(var(--spacing) * 20);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .py-4 {\n padding-block: calc(var(--spacing) * 4);\n }\n .pt-6 {\n padding-top: calc(var(--spacing) * 6);\n }\n .pb-10 {\n padding-bottom: calc(var(--spacing) * 10);\n }\n .pb-16 {\n padding-bottom: calc(var(--spacing) * 16);\n }\n .text-left {\n text-align: left;\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 .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-normal {\n --tw-font-weight: var(--font-weight-normal);\n font-weight: var(--font-weight-normal);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-gray-200 {\n color: var(--color-gray-200);\n }\n .text-gray-300 {\n color: var(--color-gray-300);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-900 {\n color: var(--color-gray-900);\n }\n .text-white {\n color: var(--color-white);\n }\n .opacity-50 {\n opacity: 50%;\n }\n .shadow-2xl {\n --tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .shadow-md {\n --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .backdrop-blur-sm {\n --tw-backdrop-blur: blur(var(--blur-sm));\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\n }\n .transition {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-all {\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 }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\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 }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .ease-in-out {\n --tw-ease: var(--ease-in-out);\n transition-timing-function: var(--ease-in-out);\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-white\\/5 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 5%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 5%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n }\n }\n .hover\\:bg-white\\/90 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, #fff 90%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 90%, transparent);\n }\n }\n }\n }\n .hover\\:text-gray-200 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-200);\n }\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-gray-400 {\n &:focus {\n --tw-ring-color: var(--color-gray-400);\n }\n }\n .focus\\:ring-offset-1 {\n &:focus {\n --tw-ring-offset-width: 1px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .disabled\\:cursor-not-allowed {\n &:disabled {\n cursor: not-allowed;\n }\n }\n .disabled\\:bg-white\\/50 {\n &:disabled {\n background-color: color-mix(in srgb, #fff 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-white) 50%, transparent);\n }\n }\n }\n .disabled\\:opacity-50 {\n &:disabled {\n opacity: 50%;\n }\n }\n .lg\\:h-32 {\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 32);\n }\n }\n .lg\\:w-32 {\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 32);\n }\n }\n .lg\\:pb-12 {\n @media (width >= 64rem) {\n padding-bottom: calc(var(--spacing) * 12);\n }\n }\n .lg\\:text-2xl {\n @media (width >= 64rem) {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n }\n .lg\\:text-3xl {\n @media (width >= 64rem) {\n font-size: var(--text-3xl);\n line-height: var(--tw-leading, var(--text-3xl--line-height));\n }\n }\n .lg\\:text-base {\n @media (width >= 64rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n}\n.noCursor {\n cursor: none !important;\n}\n.icon-class {\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n color: var(--color-gray-400);\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\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 color: var(--color-gray-200);\n }\n }\n @media (width >= 64rem) {\n height: calc(var(--spacing) * 18);\n }\n @media (width >= 64rem) {\n width: calc(var(--spacing) * 18);\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-gradient-position {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-via {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-to {\n syntax: \"<color>\";\n inherits: false;\n initial-value: #0000;\n}\n@property --tw-gradient-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-via-stops {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-gradient-from-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 0%;\n}\n@property --tw-gradient-via-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 50%;\n}\n@property --tw-gradient-to-position {\n syntax: \"<length-percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\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 *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\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-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-backdrop-blur: initial;\n --tw-backdrop-brightness: initial;\n --tw-backdrop-contrast: initial;\n --tw-backdrop-grayscale: initial;\n --tw-backdrop-hue-rotate: initial;\n --tw-backdrop-invert: initial;\n --tw-backdrop-opacity: initial;\n --tw-backdrop-saturate: initial;\n --tw-backdrop-sepia: initial;\n --tw-duration: initial;\n --tw-ease: initial;\n }\n }\n}\n";
38
+ styleInject(css_248z$3,{"insertAt":"top"});
39
39
 
40
- const useVideoStore = create((set) => ({
40
+ const createVideoRefsSlice = (set) => ({
41
41
  videoRef: null,
42
42
  setVideoRef: (ref) => set({ videoRef: ref }),
43
43
  videoWrapperRef: null,
44
44
  setVideoWrapperRef: (ref) => set({ videoWrapperRef: ref }),
45
+ });
46
+
47
+ const createVideoPlaybackSlice = (set) => ({
45
48
  playing: false,
46
49
  setPlaying: (playing) => set({ playing }),
47
50
  isBuffering: false,
@@ -52,29 +55,41 @@ const useVideoStore = create((set) => ({
52
55
  setMuted: (muted) => set({ muted }),
53
56
  volume: 1,
54
57
  setVolume: (volume) => set({ volume }),
55
- controls: false,
56
- setControls: (controls) => set({ controls }),
58
+ });
59
+
60
+ const createVideoTimingSlice = (set) => ({
57
61
  currentTime: 0,
58
62
  setCurrentTime: (currentTime) => set({ currentTime }),
59
63
  duration: 0,
60
64
  setDuration: (duration) => set({ duration }),
65
+ bufferedProgress: 0,
66
+ setBufferedProgress: (progress) => set({ bufferedProgress: progress }),
67
+ });
68
+
69
+ const createVideoControlsSlice = (set) => ({
70
+ controls: false,
71
+ setControls: (controls) => set({ controls }),
61
72
  isFullscreen: false,
62
73
  setIsFullscreen: (isFullscreen) => set({ isFullscreen }),
74
+ });
75
+
76
+ const createVideoQualitySlice = (set) => ({
63
77
  hlsInstance: undefined,
64
78
  setHlsInstance: (hlsInstance) => set({ hlsInstance }),
65
79
  qualityLevels: undefined,
66
80
  setQualityLevels: (qualityLevels) => set({ qualityLevels }),
67
81
  activeQuality: "auto",
68
82
  setActiveQuality: (activeQuality) => set({ activeQuality }),
83
+ });
84
+
85
+ const createSubtitlesSlice = (set) => ({
69
86
  activeSubtitle: null,
70
87
  setActiveSubtitle: (subtitle) => set({ activeSubtitle: subtitle }),
71
88
  subtitles: [],
72
89
  setSubtitles: (subtitles) => set({ subtitles }),
73
- showIntroSkip: false,
74
- setShowIntroSkip: (show) => set({ showIntroSkip: show }),
75
- autoPlayNext: false,
76
- setAutoPlayNext: (value) => set({ autoPlayNext: value }),
77
- // Next Episode
90
+ });
91
+
92
+ const createEpisodesSlice = (set) => ({
78
93
  episodeList: [],
79
94
  setEpisodeList: (list) => set({ episodeList: list }),
80
95
  currentEpisodeIndex: 0,
@@ -83,10 +98,59 @@ const useVideoStore = create((set) => ({
83
98
  setShowCountdown: (show) => set({ showCountdown: show }),
84
99
  countdownTime: 10,
85
100
  setCountdownTime: (time) => set({ countdownTime: time }),
101
+ autoPlayNext: false,
102
+ setAutoPlayNext: (value) => set({ autoPlayNext: value }),
103
+ });
104
+
105
+ const createIntroSlice = (set) => ({
106
+ showIntroSkip: false,
107
+ setShowIntroSkip: (show) => set({ showIntroSkip: show }),
108
+ });
109
+
110
+ const createResetSlice = (set, get) => ({
111
+ resetStore: () => {
112
+ set({
113
+ videoRef: null,
114
+ videoWrapperRef: null,
115
+ playing: false,
116
+ isBuffering: false,
117
+ isPlaying: false,
118
+ muted: false,
119
+ volume: 1,
120
+ currentTime: 0,
121
+ duration: 0,
122
+ bufferedProgress: 0,
123
+ controls: false,
124
+ isFullscreen: false,
125
+ hlsInstance: undefined,
126
+ qualityLevels: undefined,
127
+ activeQuality: "auto",
128
+ activeSubtitle: null,
129
+ subtitles: [],
130
+ episodeList: [],
131
+ currentEpisodeIndex: 0,
132
+ showCountdown: false,
133
+ countdownTime: 10,
134
+ autoPlayNext: false,
135
+ showIntroSkip: false,
136
+ });
137
+ },
138
+ });
139
+
140
+ const useVideoStore = create()((set, get, store) => ({
141
+ ...createVideoRefsSlice(set),
142
+ ...createVideoPlaybackSlice(set),
143
+ ...createVideoTimingSlice(set),
144
+ ...createVideoControlsSlice(set),
145
+ ...createVideoQualitySlice(set),
146
+ ...createSubtitlesSlice(set),
147
+ ...createEpisodesSlice(set),
148
+ ...createIntroSlice(set),
149
+ ...createResetSlice(set),
86
150
  }));
87
151
 
88
152
  /**
89
- * @description Converts seconds to hh:mm:ss
153
+ * @description
90
154
  * @param seconds
91
155
  * @returns
92
156
  */
@@ -104,7 +168,7 @@ const timeFormat = (seconds) => {
104
168
  return `${mm}:${ss}`;
105
169
  };
106
170
  /**
107
- * @description Converts seconds to milliseconds
171
+ * @description
108
172
  * @param seconds
109
173
  * @returns
110
174
  */
@@ -112,9 +176,9 @@ const secondsToMilliseconds = (seconds) => {
112
176
  return seconds * 1000;
113
177
  };
114
178
  /**
115
- * @description get extension from url
179
+ * @description
116
180
  * @param url
117
- * @returns string | undefined
181
+ * @returns
118
182
  */
119
183
  const getExtensionFromUrl = (url) => {
120
184
  const extension = url?.split(".")?.pop();
@@ -358,14 +422,14 @@ const VideoSeekSlider = ({ max = 1000, currentTime = 0, bufferTime = 0, hideThum
358
422
  React__default.createElement(Thumb, { max: max, currentTime: currentTime, isThumbActive: isThumbActive, trackColor: trackColor })));
359
423
  };
360
424
 
361
- var css_248z$1 = ".ui-video-seek-slider {\n position: relative;\n touch-action: none;\n}\n.ui-video-seek-slider:focus {\n outline: none;\n}\n.ui-video-seek-slider .track {\n padding: 0;\n cursor: pointer;\n outline: none;\n}\n.ui-video-seek-slider .track:focus {\n border: 0;\n outline: none;\n}\n.ui-video-seek-slider .track .main {\n width: 100%;\n outline: none;\n height: 18px;\n top: 0;\n position: absolute;\n display: flex;\n align-items: center;\n box-sizing: border-box;\n}\n.ui-video-seek-slider .track .main:before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.2);\n overflow: hidden;\n transition: height 0.1s;\n outline: none;\n}\n.ui-video-seek-slider .track .main .inner-seek-block {\n position: absolute;\n width: 100%;\n height: 3px;\n transition: height 0.1s, opacity 0.4s;\n transform-origin: 0 0;\n}\n.ui-video-seek-slider .track .main:focus {\n border: 0;\n outline: none;\n}\n.ui-video-seek-slider .track .main .buffered {\n background-color: rgba(255, 255, 255, 0.3);\n z-index: 2;\n}\n.ui-video-seek-slider .track .main .seek-hover {\n background-color: rgba(255, 255, 255, 0.5);\n z-index: 1;\n}\n.ui-video-seek-slider .track .main .connect {\n background-color: #ff0000;\n z-index: 3;\n transform-origin: 0 0;\n}\n.ui-video-seek-slider .track .main.with-gap .inner-seek-block,\n.ui-video-seek-slider .track .main.with-gap:before {\n width: calc(100% - 2px);\n margin: 0 auto;\n}\n@media (hover) {\n .ui-video-seek-slider .track .main:hover:before {\n height: 8px;\n }\n .ui-video-seek-slider .track .main:hover .inner-seek-block {\n height: 8px;\n }\n}\n.ui-video-seek-slider .thumb {\n pointer-events: none;\n position: absolute;\n width: 12px;\n height: 12px;\n left: -6px;\n z-index: 4;\n top: 3px;\n}\n.ui-video-seek-slider .thumb .handler {\n border-radius: 100%;\n width: 100%;\n height: 100%;\n background-color: #ff0000;\n opacity: 0;\n transform: scale(0.4);\n transition: transform 0.2s, opacity 0.2s;\n}\n.ui-video-seek-slider .thumb.active .handler {\n opacity: 1;\n transform: scale(1);\n}\n.ui-video-seek-slider .hover-time {\n text-shadow: 1px 1px 1px #000;\n position: absolute;\n line-height: 18px;\n font-size: 16px;\n color: #ddd;\n bottom: 5px;\n left: 0;\n padding: 5px 10px;\n opacity: 0;\n pointer-events: none;\n text-align: center;\n}\n.ui-video-seek-slider .hover-time.active {\n opacity: 1;\n}\n.ui-video-seek-slider .hover-time .preview-screen {\n background-repeat: no-repeat;\n background-size: cover;\n background-position: center;\n width: 200px;\n height: 110px;\n border-radius: 5px;\n background-color: #000;\n margin: 0 auto 10px;\n}\n.ui-video-seek-slider:hover .track .main .seek-hover {\n opacity: 1;\n}\n";
362
- styleInject(css_248z$1,{"insertAt":"top"});
425
+ var css_248z$2 = ".ui-video-seek-slider {\n position: relative;\n touch-action: none;\n}\n.ui-video-seek-slider:focus {\n outline: none;\n}\n.ui-video-seek-slider .track {\n padding: 0;\n cursor: pointer;\n outline: none;\n}\n.ui-video-seek-slider .track:focus {\n border: 0;\n outline: none;\n}\n.ui-video-seek-slider .track .main {\n width: 100%;\n outline: none;\n height: 18px;\n top: 0;\n position: absolute;\n display: flex;\n align-items: center;\n box-sizing: border-box;\n}\n.ui-video-seek-slider .track .main:before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 3px;\n background-color: rgba(255, 255, 255, 0.2);\n overflow: hidden;\n transition: height 0.1s;\n outline: none;\n}\n.ui-video-seek-slider .track .main .inner-seek-block {\n position: absolute;\n width: 100%;\n height: 3px;\n transition: height 0.1s, opacity 0.4s, transform 0.2s ease-out;\n transform-origin: 0 0;\n}\n.ui-video-seek-slider .track .main:focus {\n border: 0;\n outline: none;\n}\n.ui-video-seek-slider .track .main .buffered {\n background-color: rgba(255, 255, 255, 0.3);\n z-index: 2;\n transition: transform 0.2s ease-out;\n}\n.ui-video-seek-slider .track .main .seek-hover {\n background-color: rgba(255, 255, 255, 0.5);\n z-index: 1;\n}\n.ui-video-seek-slider .track .main .connect {\n background-color: #ff0000;\n z-index: 3;\n transform-origin: 0 0;\n}\n.ui-video-seek-slider .track .main.with-gap .inner-seek-block,\n.ui-video-seek-slider .track .main.with-gap:before {\n width: calc(100% - 2px);\n margin: 0 auto;\n}\n@media (hover) {\n .ui-video-seek-slider .track .main:hover:before {\n height: 8px;\n }\n .ui-video-seek-slider .track .main:hover .inner-seek-block {\n height: 8px;\n }\n}\n.ui-video-seek-slider .thumb {\n pointer-events: none;\n position: absolute;\n width: 12px;\n height: 12px;\n left: -6px;\n z-index: 4;\n top: 3px;\n}\n.ui-video-seek-slider .thumb .handler {\n border-radius: 100%;\n width: 100%;\n height: 100%;\n background-color: #ff0000;\n opacity: 0;\n transform: scale(0.4);\n transition: transform 0.2s, opacity 0.2s;\n}\n.ui-video-seek-slider .thumb.active .handler {\n opacity: 1;\n transform: scale(1);\n}\n.ui-video-seek-slider .hover-time {\n text-shadow: 1px 1px 1px #000;\n position: absolute;\n line-height: 18px;\n font-size: 16px;\n color: #ddd;\n bottom: 5px;\n left: 0;\n padding: 5px 10px;\n opacity: 0;\n pointer-events: none;\n text-align: center;\n}\n.ui-video-seek-slider .hover-time.active {\n opacity: 1;\n}\n.ui-video-seek-slider .hover-time .preview-screen {\n background-repeat: no-repeat;\n background-size: cover;\n background-position: center;\n width: 200px;\n height: 110px;\n border-radius: 5px;\n background-color: #000;\n margin: 0 auto 10px;\n}\n.ui-video-seek-slider:hover .track .main .seek-hover {\n opacity: 1;\n}\n";
426
+ styleInject(css_248z$2,{"insertAt":"top"});
363
427
 
364
428
  const BottomControls = ({ config }) => {
365
- const { videoRef, currentTime, isFullscreen } = useVideoStore();
429
+ const { videoRef, currentTime, isFullscreen, bufferedProgress } = useVideoStore();
366
430
  const duration = videoRef?.duration;
367
431
  return (React__default.createElement("div", { className: "px-10" },
368
- React__default.createElement(VideoSeekSlider, { max: secondsToMilliseconds(duration || 0), currentTime: secondsToMilliseconds(currentTime || 0), bufferTime: secondsToMilliseconds(0), onChange: (currentTime) => {
432
+ React__default.createElement(VideoSeekSlider, { max: secondsToMilliseconds(duration || 0), currentTime: secondsToMilliseconds(currentTime || 0), bufferTime: secondsToMilliseconds((duration || 0) * (bufferedProgress / 100)), onChange: (currentTime) => {
369
433
  if (videoRef) {
370
434
  videoRef.currentTime = currentTime / 1000;
371
435
  }
@@ -389,7 +453,23 @@ const Tooltip = ({ children, title, position = "top", }) => {
389
453
  visible && (React__default.createElement("div", { className: `absolute z-50 px-3 py-1 text-sm text-white bg-gray-900 rounded-md shadow-md transition-opacity duration-200 ease-in-out ${positionStyles[position]}` }, title))));
390
454
  };
391
455
 
392
- const Popover = ({ button, children, closeOnButtonClick = false, }) => {
456
+ var css_248z$1 = ".icon-button {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.icon-button:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .icon-button {\n width: 32px;\n height: 32px;\n }\n}\n\n/* styles/fullscreen-toggle.css */\n.fullscreen-icon {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.fullscreen-icon:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .fullscreen-icon {\n width: 32px;\n height: 32px;\n }\n}\n\n/* styles/pi-picture-in-picture-toggle.css */\n.pip-toggle {\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.pip-toggle:hover {\n color: #e5e7eb;\n}\n\n.pip-icon {\n width: 15px;\n height: 15px;\n}\n\n@media (min-width: 1024px) {\n .pip-icon {\n width: 28px;\n height: 28px;\n }\n}\n";
457
+ styleInject(css_248z$1,{"insertAt":"top"});
458
+
459
+ const FullScreenToggle = ({ isFullScreen, onClick, className = "fullscreen-icon", }) => {
460
+ return (React__default.createElement("div", { onClick: onClick }, isFullScreen ? (React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25", className: className },
461
+ React__default.createElement("path", { fill: "currentColor", fillRule: "evenodd", d: "M2.849 4.71l4.77 4.77H5.857a1.111 1.111 0 1 0 0 2.221H10.3a1.11 1.11 0 0 0 1.111-1.11V6.145a1.111 1.111 0 0 0-2.222 0v1.762l-4.77-4.77A1.111 1.111 0 1 0 2.85 4.709zm19.349 16.206l-4.77-4.77h1.762a1.111 1.111 0 0 0 0-2.223h-4.444c-.614 0-1.111.498-1.111 1.112v4.444a1.111 1.111 0 0 0 2.222 0v-1.762l4.77 4.77a1.111 1.111 0 1 0 1.571-1.571z", clipRule: "evenodd" }))) : (React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25", className: className },
462
+ React__default.createElement("path", { fill: "currentColor", d: "M4.746 8.056V6.294L18.73 20.278h-1.762a1.111 1.111 0 1 0 0 2.222h4.444a1.11 1.11 0 0 0 1.111-1.111v-4.445a1.111 1.111 0 0 0-2.222 0v1.762L6.317 4.722h1.762a1.111 1.111 0 1 0 0-2.222H3.635c-.614 0-1.112.497-1.112 1.111v4.445a1.111 1.111 0 1 0 2.223 0z" })))));
463
+ };
464
+
465
+ const PiPictureInPictureToggle = ({ onClick, className = "", }) => {
466
+ return (React__default.createElement("div", { onClick: onClick, className: `pip-toggle` },
467
+ React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", fill: "none", viewBox: "0 0 24 24", className: `pip-icon ${className}` },
468
+ React__default.createElement("rect", { width: "9", height: "6", x: "11", y: "11.99", fill: "#fff", rx: "1" }),
469
+ React__default.createElement("rect", { width: "22", height: "18", x: "1", y: "3", stroke: "#B3B3B3", strokeWidth: "2", rx: "3" }))));
470
+ };
471
+
472
+ const Popover = ({ button, children, closeOnButtonClick = false, className = "", align = "left", }) => {
393
473
  const [isOpen, setIsOpen] = useState(false);
394
474
  const popoverRef = useRef(null);
395
475
  const buttonRef = useRef(null);
@@ -418,82 +498,236 @@ const Popover = ({ button, children, closeOnButtonClick = false, }) => {
418
498
  const togglePopover = () => {
419
499
  setIsOpen((prev) => (closeOnButtonClick ? !prev : true));
420
500
  };
501
+ // Get alignment classes
502
+ const getAlignmentClasses = () => {
503
+ switch (align) {
504
+ case "center":
505
+ return "left-1/2 -translate-x-1/2";
506
+ case "right":
507
+ return "right-0";
508
+ case "left":
509
+ default:
510
+ return "left-0";
511
+ }
512
+ };
513
+ // Arrow is always centered regardless of popover alignment
514
+ const getArrowPositionClasses = () => {
515
+ return "left-1/2 -translate-x-1/2";
516
+ };
421
517
  return (React__default.createElement("div", { className: "relative inline-block" },
422
518
  React__default.createElement("div", { ref: buttonRef, onClick: togglePopover, tabIndex: 0, role: "button" }, button),
423
- isOpen && (React__default.createElement("div", { ref: popoverRef, className: "absolute left-0 mt-2 w-fit bg-white shadow-lg rounded-lg border border-gray-200 z-50 p-4 transition-all duration-200" },
424
- React__default.createElement("div", { className: "absolute -top-2 left-4 w-3 h-3 bg-white transform rotate-45 border-l border-t border-gray-200 z-[-1]" }),
519
+ isOpen && (React__default.createElement("div", { ref: popoverRef, className: `absolute ${getAlignmentClasses()} mt-2 w-fit bg-[#3a4049] text-white shadow-2xl rounded-lg border border-white/10 z-50 p-0 transition-all duration-200 ${className}` },
520
+ React__default.createElement("div", { className: `absolute -top-2 ${getArrowPositionClasses()} w-3 h-3 bg-[#3a4049] transform rotate-45 border-l border-t border-white/10 z-[-1]` }),
425
521
  children))));
426
522
  };
427
523
 
428
- var css_248z = ".icon-button {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.icon-button:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .icon-button {\n width: 32px;\n height: 32px;\n }\n}\n\n/* styles/fullscreen-toggle.css */\n.fullscreen-icon {\n width: 20px;\n height: 20px;\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.fullscreen-icon:hover {\n color: #e5e7eb;\n}\n\n@media (min-width: 1024px) {\n .fullscreen-icon {\n width: 32px;\n height: 32px;\n }\n}\n\n/* styles/pi-picture-in-picture-toggle.css */\n.pip-toggle {\n cursor: pointer;\n color: #9ca3af;\n transition: color 0.2s ease-in-out;\n}\n\n.pip-toggle:hover {\n color: #e5e7eb;\n}\n\n.pip-icon {\n width: 15px;\n height: 15px;\n}\n\n@media (min-width: 1024px) {\n .pip-icon {\n width: 28px;\n height: 28px;\n }\n}\n";
429
- styleInject(css_248z,{"insertAt":"top"});
430
-
431
- const FullScreenToggle = ({ isFullScreen, onClick, className = "fullscreen-icon", }) => {
432
- return (React__default.createElement("div", { onClick: onClick }, isFullScreen ? (React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25", className: className },
433
- React__default.createElement("path", { fill: "currentColor", fillRule: "evenodd", d: "M2.849 4.71l4.77 4.77H5.857a1.111 1.111 0 1 0 0 2.221H10.3a1.11 1.11 0 0 0 1.111-1.11V6.145a1.111 1.111 0 0 0-2.222 0v1.762l-4.77-4.77A1.111 1.111 0 1 0 2.85 4.709zm19.349 16.206l-4.77-4.77h1.762a1.111 1.111 0 0 0 0-2.223h-4.444c-.614 0-1.111.498-1.111 1.112v4.444a1.111 1.111 0 0 0 2.222 0v-1.762l4.77 4.77a1.111 1.111 0 1 0 1.571-1.571z", clipRule: "evenodd" }))) : (React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25", className: className },
434
- React__default.createElement("path", { fill: "currentColor", d: "M4.746 8.056V6.294L18.73 20.278h-1.762a1.111 1.111 0 1 0 0 2.222h4.444a1.11 1.11 0 0 0 1.111-1.111v-4.445a1.111 1.111 0 0 0-2.222 0v1.762L6.317 4.722h1.762a1.111 1.111 0 1 0 0-2.222H3.635c-.614 0-1.112.497-1.112 1.111v4.445a1.111 1.111 0 1 0 2.223 0z" })))));
435
- };
436
-
437
- const PiPictureInPictureToggle = ({ onClick, className = "", }) => {
438
- return (React__default.createElement("div", { onClick: onClick, className: `pip-toggle` },
439
- React__default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", fill: "none", viewBox: "0 0 24 24", className: `pip-icon ${className}` },
440
- React__default.createElement("rect", { width: "9", height: "6", x: "11", y: "11.99", fill: "#fff", rx: "1" }),
441
- React__default.createElement("rect", { width: "22", height: "18", x: "1", y: "3", stroke: "#B3B3B3", strokeWidth: "2", rx: "3" }))));
524
+ const Settings = ({ iconClassName }) => {
525
+ const { qualityLevels, hlsInstance, setActiveQuality, activeQuality, subtitles, activeSubtitle, setActiveSubtitle, videoRef, } = useVideoStore();
526
+ const [speed, setSpeed] = React.useState(1);
527
+ const [activeMenu, setActiveMenu] = React.useState("main");
528
+ const handleSpeedChange = (newSpeed) => {
529
+ setSpeed(newSpeed);
530
+ if (videoRef) {
531
+ videoRef.playbackRate = newSpeed;
532
+ }
533
+ };
534
+ const uniqueQualityLevels = React.useMemo(() => {
535
+ if (!qualityLevels)
536
+ return [];
537
+ const seenHeights = new Set();
538
+ const unique = [];
539
+ qualityLevels.forEach((level, originalIndex) => {
540
+ if (seenHeights.has(level.height))
541
+ return;
542
+ seenHeights.add(level.height);
543
+ unique.push({
544
+ height: level.height,
545
+ bitrate: level.bitrate,
546
+ originalIndex,
547
+ });
548
+ });
549
+ return unique;
550
+ }, [qualityLevels]);
551
+ const speedOptions = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
552
+ const handleBack = () => setActiveMenu("main");
553
+ // Get quality label for display
554
+ const getQualityLabel = () => {
555
+ if (activeQuality === "auto")
556
+ return "Auto";
557
+ const level = uniqueQualityLevels.find((l) => String(l.height) === activeQuality);
558
+ return level ? `${level.height}p` : "Auto";
559
+ };
560
+ // Get quality label: show explicit resolution to avoid duplicates
561
+ const getQualityName = (height) => {
562
+ if (!height || height <= 0)
563
+ return "Auto";
564
+ return `${height}p`;
565
+ };
566
+ // Get estimated data usage using bitrate when available
567
+ const getDataUsage = (height, bitrate) => {
568
+ // bitrate in bits/sec -> GB/hour
569
+ if (bitrate && bitrate > 0) {
570
+ const gbPerHour = (bitrate * 3600) / 8 / 1e9;
571
+ const rounded = gbPerHour.toFixed(2);
572
+ return `Uses about ${rounded} GB per hour`;
573
+ }
574
+ // Fallback by resolution when bitrate missing
575
+ if (height >= 2160)
576
+ return "Uses about 7.00 GB per hour";
577
+ if (height >= 1440)
578
+ return "Uses about 3.50 GB per hour";
579
+ if (height >= 1080)
580
+ return "Uses about 2.50 GB per hour";
581
+ if (height >= 720)
582
+ return "Uses about 1.00 GB per hour";
583
+ if (height >= 480)
584
+ return "Uses about 0.70 GB per hour";
585
+ if (height >= 360)
586
+ return "Uses about 0.50 GB per hour";
587
+ return "Uses about 0.30 GB per hour";
588
+ };
589
+ return (React.createElement(Tooltip, { title: "Settings" },
590
+ React.createElement(Popover, { button: React.createElement(Settings$1, { className: iconClassName }), align: "center" },
591
+ React.createElement("div", { className: "bg-[#3a4049] text-white rounded-[7px] w-80 overflow-hidden" },
592
+ activeMenu === "main" && (React.createElement("div", { className: "p-4" },
593
+ React.createElement("h3", { className: "text-white font-bold text-xl mb-4" }, "Settings"),
594
+ React.createElement("p", { className: "text-gray-300 text-sm mb-4" }, "Customize playback"),
595
+ React.createElement("div", { className: "space-y-0 border-t border-gray-600" },
596
+ React.createElement("button", { onClick: () => setActiveMenu("quality"), className: "w-full flex items-center justify-between py-4 border-b border-gray-600 rounded-[5px] transition-colors" },
597
+ React.createElement("div", { className: "flex items-center gap-3" },
598
+ React.createElement("div", { className: "p-2 bg-blue-500 rounded-md" },
599
+ React.createElement("svg", { className: "w-5 h-5 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
600
+ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }))),
601
+ React.createElement("div", { className: "text-left" },
602
+ React.createElement("div", { className: "text-white font-semibold" }, "Quality"),
603
+ React.createElement("div", { className: "text-gray-400 text-sm" }, getQualityLabel()))),
604
+ React.createElement(ChevronRight, { className: "w-5 h-5 text-gray-400" })),
605
+ React.createElement("button", { onClick: () => setActiveMenu("subtitles"), className: "w-full flex items-center justify-between py-4 border-b border-gray-600 rounded-[5px] transition-colors" },
606
+ React.createElement("div", { className: "flex items-center gap-3" },
607
+ React.createElement("div", { className: "p-2 bg-purple-500 rounded-md" },
608
+ React.createElement("svg", { className: "w-5 h-5 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
609
+ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" }))),
610
+ React.createElement("div", { className: "text-left" },
611
+ React.createElement("div", { className: "text-white font-semibold" }, "Subtitles"),
612
+ React.createElement("div", { className: "text-gray-400 text-sm" }, !activeSubtitle ? "Off" : activeSubtitle.label))),
613
+ React.createElement(ChevronRight, { className: "w-5 h-5 text-gray-400" })),
614
+ React.createElement("button", { onClick: () => setActiveMenu("speed"), className: "w-full flex items-center justify-between py-4 rounded-[5px] transition-colors" },
615
+ React.createElement("div", { className: "flex items-center gap-3" },
616
+ React.createElement("div", { className: "p-2 bg-green-500 rounded-md" },
617
+ React.createElement("svg", { className: "w-5 h-5 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
618
+ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 10V3L4 14h7v7l9-11h-7z" }))),
619
+ React.createElement("div", { className: "text-left" },
620
+ React.createElement("div", { className: "text-white font-semibold" }, "Speed"),
621
+ React.createElement("div", { className: "text-gray-400 text-sm" },
622
+ speed,
623
+ "x"))),
624
+ React.createElement(ChevronRight, { className: "w-5 h-5 text-gray-400" }))))),
625
+ activeMenu === "quality" && (React.createElement("div", { className: "p-4" },
626
+ React.createElement("div", { className: "flex items-center gap-3 mb-4" },
627
+ React.createElement("button", { onClick: handleBack, className: "p-1 rounded-md transition-colors" },
628
+ React.createElement(ChevronRight, { className: "w-6 h-6 text-white rotate-180" })),
629
+ React.createElement("h3", { className: "text-white font-bold text-xl" }, "Video Quality")),
630
+ React.createElement("div", { className: "space-y-3" },
631
+ React.createElement("button", { onClick: () => {
632
+ if (hlsInstance) {
633
+ hlsInstance.currentLevel = -1;
634
+ setActiveQuality("auto");
635
+ }
636
+ }, className: `w-full text-left px-4 py-3 rounded-md transition-all ${activeQuality === "auto"
637
+ ? "bg-white/10"
638
+ : "hover:bg-white/5"}` },
639
+ React.createElement("div", { className: "flex items-start justify-between" },
640
+ React.createElement("div", null,
641
+ React.createElement("div", { className: "text-white font-semibold text-lg mb-1" }, "Auto"),
642
+ React.createElement("div", { className: "text-gray-400 text-sm" }, "Adjust to your connection")),
643
+ activeQuality === "auto" && (React.createElement(Check, { className: "w-6 h-6 text-white mt-1" })))),
644
+ uniqueQualityLevels
645
+ .map((level) => (React.createElement("button", { key: level.originalIndex, onClick: () => {
646
+ if (hlsInstance) {
647
+ hlsInstance.currentLevel = level.originalIndex;
648
+ setActiveQuality(String(level.height));
649
+ }
650
+ }, className: `w-full text-left px-4 py-3 rounded-md transition-all ${activeQuality === String(level.height)
651
+ ? "bg-white/10"
652
+ : "hover:bg-white/5"}` },
653
+ React.createElement("div", { className: "flex items-start justify-between" },
654
+ React.createElement("div", null,
655
+ React.createElement("div", { className: "text-white font-semibold text-lg mb-1" }, getQualityName(level.height)),
656
+ React.createElement("div", { className: "text-gray-400 text-sm" }, getDataUsage(level.height, level.bitrate))),
657
+ activeQuality === String(level.height) && (React.createElement(Check, { className: "w-6 h-6 text-white mt-1" }))))))
658
+ .reverse()))),
659
+ activeMenu === "subtitles" && (React.createElement("div", { className: "p-4" },
660
+ React.createElement("div", { className: "flex items-center gap-3 mb-4" },
661
+ React.createElement("button", { onClick: handleBack, className: "p-1 hover:bg-white/10 rounded-md transition-colors" },
662
+ React.createElement(ChevronRight, { className: "w-6 h-6 text-white rotate-180" })),
663
+ React.createElement("h3", { className: "text-white font-bold text-xl" }, "Subtitles")),
664
+ React.createElement("div", { className: "space-y-3" },
665
+ React.createElement("button", { onClick: () => setActiveSubtitle(null), className: `w-full text-left px-4 py-3 rounded-[5px] transition-all flex items-center justify-between ${!activeSubtitle ? "bg-[#454545]" : ""}` },
666
+ React.createElement("span", { className: "text-white font-semibold text-lg" }, "Off"),
667
+ !activeSubtitle && React.createElement(Check, { className: "w-6 h-6 text-white" })),
668
+ subtitles?.map((subtitle, index) => (React.createElement("button", { key: index, onClick: () => setActiveSubtitle(subtitle), className: `w-full text-left px-4 py-3 rounded-md transition-all flex items-center justify-between ${activeSubtitle?.label === subtitle.label
669
+ ? "bg-white/10"
670
+ : "hover:bg-white/5"}` },
671
+ React.createElement("span", { className: "text-white font-semibold text-lg" }, subtitle.label),
672
+ activeSubtitle?.label === subtitle.label && (React.createElement(Check, { className: "w-6 h-6 text-white" })))))))),
673
+ activeMenu === "speed" && (React.createElement("div", { className: "p-4" },
674
+ React.createElement("div", { className: "flex items-center gap-3 mb-4" },
675
+ React.createElement("button", { onClick: handleBack, className: "p-1 hover:bg-white/10 rounded-md transition-colors" },
676
+ React.createElement(ChevronRight, { className: "w-6 h-6 text-white rotate-180" })),
677
+ React.createElement("h3", { className: "text-white font-bold text-xl" }, "Playback Speed")),
678
+ React.createElement("div", { className: "space-y-3 max-h-80 overflow-y-auto" }, speedOptions.map((s) => (React.createElement("button", { key: s, onClick: () => handleSpeedChange(s), className: `w-full text-left px-4 py-3 rounded-[5px] transition-all flex items-center justify-between ${speed === s ? "bg-[#454545]" : ""}` },
679
+ React.createElement("span", { className: "text-white font-semibold text-lg" }, s === 1 ? "Normal" : `${s}x`),
680
+ speed === s && React.createElement(Check, { className: "w-6 h-6 text-white" })))))))))));
442
681
  };
443
682
 
444
683
  const ControlsHeader = ({ config }) => {
445
684
  const iconClassName = "icon-button";
446
- const { videoWrapperRef, videoRef, qualityLevels, hlsInstance, setActiveQuality, activeQuality, subtitles, activeSubtitle, setActiveSubtitle, episodeList, currentEpisodeIndex, } = useVideoStore();
447
- const [speed, setSpeed] = React.useState(1);
685
+ const { videoWrapperRef, videoRef, episodeList, currentEpisodeIndex, resetStore, } = useVideoStore();
448
686
  const [isPipActive, setIsPipActive] = React.useState(false);
449
- const isFullscreen = document.fullscreenElement !== null;
687
+ const [isFullscreen, setIsFullscreen] = React.useState(false);
450
688
  const handleFullscreen = () => {
451
- if (isPipActive)
689
+ if (!screenfull.isEnabled || isPipActive)
452
690
  return;
453
- if (document.fullscreenElement) {
454
- document.exitFullscreen();
691
+ if (screenfull.isFullscreen) {
692
+ screenfull.exit();
455
693
  }
456
- else {
457
- videoWrapperRef?.requestFullscreen();
694
+ else if (videoWrapperRef) {
695
+ screenfull.request(videoWrapperRef);
458
696
  }
459
697
  };
698
+ React.useEffect(() => {
699
+ if (!screenfull.isEnabled)
700
+ return;
701
+ const changeHandler = () => setIsFullscreen(screenfull.isFullscreen);
702
+ screenfull.on("change", changeHandler);
703
+ return () => {
704
+ screenfull.off("change", changeHandler);
705
+ };
706
+ }, []);
460
707
  const handleMute = () => {
461
708
  if (videoRef) {
462
709
  videoRef.muted = !videoRef.muted;
463
710
  }
464
711
  };
465
- const handleSpeedChange = (newSpeed) => {
466
- setSpeed(newSpeed);
467
- if (videoRef) {
468
- videoRef.playbackRate = newSpeed;
469
- }
470
- };
471
712
  const handlePipToggle = async () => {
472
- if (videoRef) {
713
+ if (!videoRef)
714
+ return;
715
+ try {
473
716
  if (!document.pictureInPictureElement && !isPipActive) {
474
- try {
475
- await videoRef.requestPictureInPicture();
476
- setIsPipActive(true);
477
- }
478
- catch (error) {
479
- console.error("PiP mode failed:", error);
480
- }
717
+ await videoRef.requestPictureInPicture();
718
+ setIsPipActive(true);
481
719
  }
482
720
  else if (document.pictureInPictureElement && isPipActive) {
483
- try {
484
- await document.exitPictureInPicture();
485
- setIsPipActive(false);
486
- }
487
- catch (error) {
488
- console.error("Exit PiP failed:", error);
489
- }
721
+ await document.exitPictureInPicture();
722
+ setIsPipActive(false);
490
723
  }
491
724
  }
725
+ catch (error) {
726
+ console.error("PiP toggle failed:", error);
727
+ }
492
728
  };
493
729
  React.useEffect(() => {
494
- const handlePipChange = () => {
495
- setIsPipActive(!!document.pictureInPictureElement);
496
- };
730
+ const handlePipChange = () => setIsPipActive(!!document.pictureInPictureElement);
497
731
  document.addEventListener("enterpictureinpicture", handlePipChange);
498
732
  document.addEventListener("leavepictureinpicture", handlePipChange);
499
733
  return () => {
@@ -501,20 +735,12 @@ const ControlsHeader = ({ config }) => {
501
735
  document.removeEventListener("leavepictureinpicture", handlePipChange);
502
736
  };
503
737
  }, []);
504
- const uniqueQualityLevels = React.useMemo(() => {
505
- if (!qualityLevels)
506
- return [];
507
- const seenHeights = new Set();
508
- return qualityLevels.filter((level) => {
509
- if (seenHeights.has(level.height)) {
510
- return false;
511
- }
512
- else {
513
- seenHeights.add(level.height);
514
- return true;
515
- }
516
- });
517
- }, [qualityLevels]);
738
+ const handleClose = () => {
739
+ resetStore();
740
+ if (config?.onClose) {
741
+ config.onClose();
742
+ }
743
+ };
518
744
  return (React.createElement("div", { className: "flex items-center justify-between p-10 bg-gradient-to-b from-black" },
519
745
  React.createElement("div", { className: "flex" },
520
746
  React.createElement("div", null,
@@ -523,60 +749,14 @@ const ControlsHeader = ({ config }) => {
523
749
  : config?.title),
524
750
  config?.isTrailer && (React.createElement("p", { className: "text-gray-300 text-sm lg:text-base font-normal" }, "Trailer")))),
525
751
  React.createElement("div", { className: "flex items-center gap-7 text-white" },
526
- React.createElement("div", null,
527
- React.createElement(Tooltip, { title: "Settings" },
528
- React.createElement(Popover, { button: React.createElement(Settings, { className: iconClassName }) },
529
- React.createElement("div", { className: "bg-white/90 backdrop-blur-md text-gray-900 rounded-md w-56 p-2" },
530
- React.createElement("div", { className: "mb-2" },
531
- React.createElement("p", { className: "font-semibold mb-1 px-3 py-1 text-gray-700" }, "Quality"),
532
- React.createElement("div", { className: "flex flex-col gap-1" },
533
- React.createElement("button", { onClick: () => {
534
- if (hlsInstance) {
535
- hlsInstance.currentLevel = -1;
536
- setActiveQuality("auto");
537
- }
538
- }, className: `flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-200 ${activeQuality === "auto"
539
- ? "bg-green-100 font-semibold"
540
- : ""}` },
541
- activeQuality === "auto" && (React.createElement(FaCheck, { className: "text-green-500" })),
542
- "Auto"),
543
- uniqueQualityLevels
544
- .map((level, index) => (React.createElement("button", { key: index, onClick: () => {
545
- if (hlsInstance) {
546
- hlsInstance.currentLevel = index;
547
- setActiveQuality(String(level.height));
548
- }
549
- }, className: `flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-200 ${activeQuality === String(level.height)
550
- ? "bg-green-100 font-semibold"
551
- : ""}` },
552
- activeQuality === String(level.height) && (React.createElement(FaCheck, { className: "text-green-500" })),
553
- level.height,
554
- "p")))
555
- .reverse())),
556
- React.createElement("div", { className: "mb-2" },
557
- React.createElement("p", { className: "font-semibold mb-1 px-3 py-1 text-gray-700" }, "Subtitles"),
558
- React.createElement("div", { className: "flex flex-col gap-1" },
559
- React.createElement("button", { onClick: () => setActiveSubtitle(null), className: `flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-200 ${!activeSubtitle ? "bg-green-100 font-semibold" : ""}` },
560
- !activeSubtitle && (React.createElement(FaCheck, { className: "text-green-500" })),
561
- "Off"),
562
- subtitles?.map((subtitle, index) => (React.createElement("button", { key: index, onClick: () => setActiveSubtitle(subtitle), className: `flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-200 ${activeSubtitle?.label === subtitle.label
563
- ? "bg-green-100 font-semibold"
564
- : ""}` },
565
- activeSubtitle?.label === subtitle.label && (React.createElement(FaCheck, { className: "text-green-500" })),
566
- subtitle.label))))),
567
- React.createElement("div", null,
568
- React.createElement("p", { className: "font-semibold mb-1 px-3 py-1 text-gray-700" }, "Speed"),
569
- React.createElement("div", { className: "flex flex-col gap-1" }, [0.5, 1, 1.5, 2].map((s) => (React.createElement("button", { key: s, onClick: () => handleSpeedChange(s), className: `flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-200 ${speed === s ? "bg-green-100 font-semibold" : ""}` },
570
- speed === s && React.createElement(FaCheck, { className: "text-green-500" }),
571
- s,
572
- "x"))))))))),
752
+ React.createElement(Settings, { iconClassName: iconClassName }),
573
753
  React.createElement("div", { onClick: handleMute }, videoRef?.muted ? (React.createElement(Tooltip, { title: "Unmute" },
574
754
  React.createElement(IoVolumeMuteOutline, { className: iconClassName }))) : (React.createElement(Tooltip, { title: "Mute" },
575
755
  React.createElement(IoVolumeHighOutline, { className: iconClassName })))),
576
756
  React.createElement(Tooltip, { title: isPipActive
577
757
  ? "Disabled in PiP"
578
758
  : isFullscreen
579
- ? "Exit"
759
+ ? "Exit Fullscreen"
580
760
  : "Fullscreen", className: `${iconClassName} ${isPipActive ? "opacity-50 cursor-not-allowed" : ""}` },
581
761
  React.createElement("div", { onClick: handleFullscreen, className: isPipActive ? "pointer-events-none" : "" },
582
762
  React.createElement(FullScreenToggle, { isFullScreen: isFullscreen, className: iconClassName }))),
@@ -585,7 +765,7 @@ const ControlsHeader = ({ config }) => {
585
765
  React.createElement(PiPictureInPictureToggle, { className: iconClassName }))),
586
766
  config?.onClose && (React.createElement(React.Fragment, null,
587
767
  React.createElement("div", { className: "w-[2px] h-10 bg-gray-500 hover:bg-gray-300 mx-2" }),
588
- React.createElement("div", { onClick: config.onClose },
768
+ React.createElement("div", { onClick: handleClose },
589
769
  React.createElement(Tooltip, { title: "Close" },
590
770
  React.createElement(IoMdClose, { className: iconClassName }))))))));
591
771
  };
@@ -616,36 +796,34 @@ const MiddleControls = () => {
616
796
  return;
617
797
  videoRef.currentTime += 10;
618
798
  };
619
- // Handle buffering state
620
799
  useEffect(() => {
621
800
  if (!videoRef)
622
801
  return;
623
802
  const handleWaiting = () => {
624
- setIsBuffering(true);
803
+ if (!videoRef.paused) {
804
+ setIsBuffering(true);
805
+ }
625
806
  };
626
807
  const handlePlaying = () => {
627
808
  setIsBuffering(false);
628
809
  };
629
- videoRef.addEventListener("waiting", handleWaiting);
630
- videoRef.addEventListener("playing", handlePlaying);
631
- return () => {
632
- videoRef.removeEventListener("waiting", handleWaiting);
633
- videoRef.removeEventListener("playing", handlePlaying);
810
+ const handleCanPlay = () => {
811
+ setIsBuffering(false);
812
+ };
813
+ const handlePause = () => {
814
+ setIsBuffering(false);
634
815
  };
635
- }, [videoRef, setIsBuffering]);
636
- useEffect(() => {
637
- if (!videoRef)
638
- return;
639
- const handleWaiting = () => setIsBuffering(true);
640
- const handlePlaying = () => setIsBuffering(false);
641
816
  videoRef.addEventListener("waiting", handleWaiting);
642
817
  videoRef.addEventListener("playing", handlePlaying);
818
+ videoRef.addEventListener("canplay", handleCanPlay);
819
+ videoRef.addEventListener("pause", handlePause);
643
820
  return () => {
644
821
  videoRef.removeEventListener("waiting", handleWaiting);
645
822
  videoRef.removeEventListener("playing", handlePlaying);
823
+ videoRef.removeEventListener("canplay", handleCanPlay);
824
+ videoRef.removeEventListener("pause", handlePause);
646
825
  };
647
826
  }, [videoRef, setIsBuffering]);
648
- // keyboard controls
649
827
  useEffect(() => {
650
828
  const handleKeyDown = (e) => {
651
829
  if (!videoRef)
@@ -678,11 +856,12 @@ const MiddleControls = () => {
678
856
  React__default.createElement("path", { fillRule: "evenodd", d: "M33.5 0C15 0 0 15 0 33.5S15 67 33.5 67 67 52 67 33.5a2.583 2.583 0 0 0-2.58-2.53c-1.4 0-2.55 1.13-2.57 2.53 0 15.66-12.69 28.35-28.35 28.35-15.65 0-28.35-12.7-28.35-28.35 0-15.66 12.7-28.35 28.35-28.35 7.3 0 13.96 2.76 18.99 7.3.46.42.9.85 1.34 1.29h-6.59a2.58 2.58 0 0 0 0 5.16h13.75c1.42 0 2.57-1.16 2.57-2.58V2.58c0-1.43-1.15-2.58-2.57-2.58-1.43 0-2.58 1.15-2.58 2.58v8.52c-.78-.87-1.61-1.7-2.47-2.48A33.446 33.446 0 0 0 33.54 0h-.04zM33.98 41.34c-1.6-2.21-2-5.2-2-7.85 0-2.65.4-5.63 2-7.83 1.44-1.97 3.47-2.84 5.88-2.84 2.41 0 4.42.87 5.86 2.84 1.61 2.21 2.03 5.16 2.03 7.83 0 2.66-.4 5.64-2 7.85-1.43 1.97-3.47 2.84-5.89 2.84-2.41 0-4.45-.87-5.88-2.84zm-9.73-12.77l-5 1.58v-4.21l5.87-2.65h4.28v20.47h-5.15V28.57zm17.61 9.96c.61-1.33.68-3.6.68-5.04s-.07-3.7-.68-5.02c-.4-.87-1.04-1.29-2-1.29-.95 0-1.59.42-1.99 1.29-.61 1.32-.68 3.58-.68 5.02 0 1.44.07 3.71.68 5.04.4.86 1.04 1.28 1.99 1.28.96 0 1.6-.42 2-1.28z" })))));
679
857
  };
680
858
 
681
- const VideoPlayerControls = ({ config, height, width, }) => {
682
- return (React.createElement("div", { className: `absolute top-0 left-0 ${height || "h-full"} ${width || "w-full"} bg-[rgba(0,0,0,0.5)] flex flex-col justify-between` },
683
- React.createElement(ControlsHeader, { config: config?.headerConfig?.config }),
684
- React.createElement(MiddleControls, null),
685
- React.createElement(BottomControls, { config: config?.bottomConfig?.config })));
859
+ const VideoPlayerControls = ({ config, }) => {
860
+ return (React.createElement("div", { className: "px-20" },
861
+ React.createElement("div", { className: "absolute top-0 left-0 h-full w-full bg-[rgba(0,0,0,0.5)] flex flex-col justify-between" },
862
+ React.createElement(ControlsHeader, { config: config?.headerConfig?.config }),
863
+ React.createElement(MiddleControls, null),
864
+ React.createElement(BottomControls, { config: config?.bottomConfig?.config }))));
686
865
  };
687
866
 
688
867
  const VideoActionButton = ({ text, onClick, icon, disabled = false, position = "left", }) => {
@@ -725,48 +904,22 @@ const Overlay = ({ config }) => {
725
904
  setCountdownTime(countdownTime - 1);
726
905
  }, 1000);
727
906
  }
728
- else if (showCountdown && countdownTime === 0 && episodeList.length > 0) {
729
- const nextIndex = currentEpisodeIndex + 1;
730
- if (nextIndex < episodeList.length) {
731
- setCurrentEpisodeIndex(nextIndex);
732
- setAutoPlayNext(true);
733
- if (videoRef && episodeList[nextIndex]) {
734
- videoRef.src = episodeList[nextIndex].url;
735
- videoRef
736
- .play()
737
- .catch((err) => console.error("Auto-play failed:", err));
738
- }
739
- }
740
- else {
741
- if (onClose)
742
- onClose();
743
- }
744
- setShowCountdown(false);
745
- }
746
907
  return () => {
747
908
  if (timer)
748
909
  clearInterval(timer);
749
910
  };
750
- }, [
751
- showCountdown,
752
- countdownTime,
753
- episodeList.length,
754
- setCountdownTime,
755
- setCurrentEpisodeIndex,
756
- currentEpisodeIndex,
757
- setAutoPlayNext,
758
- videoRef,
759
- episodeList,
760
- onClose,
761
- ]);
911
+ }, [showCountdown, countdownTime, episodeList.length, setCountdownTime]);
762
912
  const handleNextEpisodeManually = () => {
763
913
  const nextIndex = currentEpisodeIndex + 1;
764
914
  if (nextIndex < episodeList.length && videoRef && episodeList[nextIndex]) {
765
915
  setCurrentEpisodeIndex(nextIndex);
766
916
  setAutoPlayNext(true);
767
917
  videoRef.src = episodeList[nextIndex].url;
768
- videoRef.play().catch((err) => console.error("Manual play failed:", err));
918
+ videoRef
919
+ .play()
920
+ .catch((err) => console.error("Manual play failed:", err));
769
921
  setShowCountdown(false);
922
+ setCountdownTime(10);
770
923
  }
771
924
  else if (onClose) {
772
925
  onClose();
@@ -776,16 +929,125 @@ const Overlay = ({ config }) => {
776
929
  controls && React.createElement(VideoPlayerControls, { config: config }),
777
930
  showCountdown &&
778
931
  episodeList.length > 0 &&
779
- currentEpisodeIndex + 1 < episodeList.length && (React.createElement(VideoActionButton, { text: "Next Episode", onClick: handleNextEpisodeManually, icon: React.createElement(FaGooglePlay, { className: "text-black" }), disabled: currentEpisodeIndex + 1 >= episodeList.length, position: "right" }))));
932
+ currentEpisodeIndex + 1 < episodeList.length && (React.createElement(VideoActionButton, { text: "Next Episode", onClick: handleNextEpisodeManually, icon: React.createElement(ArrowRight, { className: "h-5 w-5 text-gray-900" }), disabled: currentEpisodeIndex + 1 >= episodeList.length, position: "right" }))));
780
933
  };
781
934
 
782
- const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrailer, className, type, height, width, timeCodes, getPreviewScreenUrl, tracking, subtitles, episodeList, currentEpisodeIndex = 0, nextEpisodeConfig, }) => {
783
- const { setVideoRef, setCurrentTime, setVideoWrapperRef, videoRef, setQualityLevels, setHlsInstance, setDuration, setIsPlaying, activeSubtitle, setSubtitles, setEpisodeList, setCurrentEpisodeIndex, setShowCountdown, } = useVideoStore();
784
- const [showSkipIntro, setShowSkipIntro] = useState(false);
785
- const onRightClick = (e) => {
786
- e.preventDefault();
935
+ const SubtitleOverlay = ({ styleConfig }) => {
936
+ const { videoRef, activeSubtitle } = useVideoStore();
937
+ const [currentSubtitle, setCurrentSubtitle] = useState("");
938
+ const [isVisible, setIsVisible] = useState(false);
939
+ useEffect(() => {
940
+ if (!videoRef)
941
+ return;
942
+ const handleTimeUpdate = () => {
943
+ if (!activeSubtitle) {
944
+ setCurrentSubtitle("");
945
+ setIsVisible(false);
946
+ return;
947
+ }
948
+ const currentTime = videoRef.currentTime;
949
+ const textTracks = Array.from(videoRef.textTracks);
950
+ console.log("Available text tracks:", textTracks.map((t) => ({
951
+ label: t.label,
952
+ mode: t.mode,
953
+ cues: t.cues?.length,
954
+ })));
955
+ const activeTrack = textTracks.find((track) => track.mode === "showing" && track.label === activeSubtitle.label);
956
+ console.log("Active track found:", !!activeTrack, "Current time:", currentTime);
957
+ if (activeTrack && activeTrack.cues) {
958
+ const activeCues = Array.from(activeTrack.cues).filter((cue) => currentTime >= cue.startTime && currentTime <= cue.endTime);
959
+ if (activeCues.length > 0) {
960
+ const cue = activeCues[0];
961
+ let cueText = "";
962
+ try {
963
+ if ("text" in cue) {
964
+ cueText = cue.text;
965
+ }
966
+ else if (typeof cue.getCueAsHTML === "function") {
967
+ const htmlElement = cue.getCueAsHTML();
968
+ cueText =
969
+ htmlElement?.textContent || htmlElement?.innerText || "";
970
+ }
971
+ else {
972
+ cueText = cue.toString() || "";
973
+ }
974
+ }
975
+ catch (error) {
976
+ console.warn("Error getting subtitle text:", error);
977
+ cueText = "";
978
+ }
979
+ setCurrentSubtitle(cueText);
980
+ setIsVisible(!!cueText);
981
+ }
982
+ else {
983
+ setCurrentSubtitle("");
984
+ setIsVisible(false);
985
+ }
986
+ }
987
+ };
988
+ videoRef.addEventListener("timeupdate", handleTimeUpdate);
989
+ return () => {
990
+ videoRef.removeEventListener("timeupdate", handleTimeUpdate);
991
+ };
992
+ }, [videoRef, activeSubtitle]);
993
+ useEffect(() => {
994
+ if (!activeSubtitle) {
995
+ setCurrentSubtitle("");
996
+ setIsVisible(false);
997
+ }
998
+ }, [activeSubtitle]);
999
+ if (!isVisible || !currentSubtitle)
1000
+ return null;
1001
+ const getPositionStyles = () => {
1002
+ const position = styleConfig?.position || "bottom";
1003
+ switch (position) {
1004
+ case "top":
1005
+ return {
1006
+ top: "10%",
1007
+ left: "50%",
1008
+ transform: "translateX(-50%)",
1009
+ };
1010
+ case "center":
1011
+ return {
1012
+ top: "50%",
1013
+ left: "50%",
1014
+ transform: "translate(-50%, -50%)",
1015
+ };
1016
+ case "bottom":
1017
+ default:
1018
+ return {
1019
+ bottom: "15%",
1020
+ left: "50%",
1021
+ transform: "translateX(-50%)",
1022
+ };
1023
+ }
1024
+ };
1025
+ const subtitleStyle = {
1026
+ position: "absolute",
1027
+ ...getPositionStyles(),
1028
+ fontSize: styleConfig?.fontSize || "1.2rem",
1029
+ fontWeight: "500",
1030
+ lineHeight: "1.2",
1031
+ textAlign: "center",
1032
+ background: styleConfig?.backgroundColor || "rgba(0, 0, 0, 0.4)",
1033
+ color: styleConfig?.textColor || "#fff",
1034
+ padding: styleConfig?.padding || "8px 16px",
1035
+ borderRadius: styleConfig?.borderRadius || "5px",
1036
+ maxWidth: styleConfig?.maxWidth || "60%",
1037
+ minWidth: "fit-content",
1038
+ boxShadow: "0 6px 20px rgba(0, 0, 0, 0.4)",
1039
+ backdropFilter: "blur(6px)",
1040
+ border: "1px solid rgba(255, 255, 255, 0.2)",
1041
+ transition: "all 0.2s ease-in-out",
1042
+ opacity: isVisible ? 1 : 0,
1043
+ zIndex: 10,
1044
+ pointerEvents: "none",
787
1045
  };
788
- // === VIDEO SOURCE INIT ===
1046
+ return React__default.createElement("div", { style: subtitleStyle }, currentSubtitle);
1047
+ };
1048
+
1049
+ const useVideoSource = (trackSrc, type) => {
1050
+ const { videoRef, setQualityLevels, setHlsInstance } = useVideoStore();
789
1051
  useEffect(() => {
790
1052
  if (!videoRef)
791
1053
  return;
@@ -816,8 +1078,11 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
816
1078
  videoRef.src = trackSrc;
817
1079
  setQualityLevels([]);
818
1080
  }
819
- }, [trackSrc, videoRef]);
820
- // === SUBTITLES ===
1081
+ }, [trackSrc, videoRef, type, setQualityLevels, setHlsInstance]);
1082
+ };
1083
+
1084
+ const useSubtitles = (subtitles) => {
1085
+ const { videoRef, activeSubtitle, setSubtitles } = useVideoStore();
821
1086
  useEffect(() => {
822
1087
  if (videoRef) {
823
1088
  const tracks = videoRef.getElementsByTagName("track");
@@ -837,11 +1102,24 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
837
1102
  trackElement.src = activeSubtitle.url;
838
1103
  trackElement.default = false;
839
1104
  videoRef.appendChild(trackElement);
840
- const textTrack = Array.from(videoRef.textTracks).find((track) => track.label === activeSubtitle.label);
841
- if (textTrack) {
842
- textTrack.mode = "showing";
843
- console.log("Subtitle track activated:", activeSubtitle.label);
844
- }
1105
+ Array.from(videoRef.textTracks).find((track) => track.label === activeSubtitle.label);
1106
+ const handleTrackLoad = () => {
1107
+ const textTrack = Array.from(videoRef.textTracks).find((track) => track.label === activeSubtitle.label);
1108
+ if (textTrack) {
1109
+ textTrack.mode = "showing";
1110
+ console.log("Subtitle track loaded for custom rendering:", activeSubtitle.label);
1111
+ }
1112
+ };
1113
+ trackElement.addEventListener("load", handleTrackLoad);
1114
+ const attempts = [100, 500, 1000];
1115
+ attempts.forEach((delay) => {
1116
+ setTimeout(() => {
1117
+ const textTrack = Array.from(videoRef.textTracks).find((track) => track.label === activeSubtitle.label);
1118
+ if (textTrack && textTrack.mode !== "showing") {
1119
+ textTrack.mode = "showing";
1120
+ }
1121
+ }, delay);
1122
+ });
845
1123
  }
846
1124
  }
847
1125
  else {
@@ -850,8 +1128,61 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
850
1128
  });
851
1129
  }
852
1130
  }
853
- }, [activeSubtitle, videoRef, subtitles]);
854
- // === TRACKING (play/pause/watchtime) ===
1131
+ }, [videoRef, activeSubtitle, subtitles]);
1132
+ useEffect(() => {
1133
+ if (subtitles) {
1134
+ setSubtitles(subtitles);
1135
+ }
1136
+ }, [subtitles, setSubtitles]);
1137
+ };
1138
+
1139
+ const useSubtitleStyling = (config) => {
1140
+ const { videoRef } = useVideoStore();
1141
+ useEffect(() => {
1142
+ if (!videoRef)
1143
+ return;
1144
+ const applySubtitleStyles = () => {
1145
+ const style = document.createElement("style");
1146
+ style.id = "custom-subtitle-styles";
1147
+ const existingStyle = document.getElementById("custom-subtitle-styles");
1148
+ if (existingStyle) {
1149
+ existingStyle.remove();
1150
+ }
1151
+ const styles = `
1152
+ .video-player video::cue {
1153
+ font-size: ${config?.fontSize || "1.75rem"} !important;
1154
+ background: ${config?.backgroundColor ||
1155
+ "linear-gradient(135deg, #fbbf24, #f59e0b)"} !important;
1156
+ color: ${config?.textColor || "#000000"} !important;
1157
+ border-radius: ${config?.borderRadius || "12px"} !important;
1158
+ padding: ${config?.padding || "12px 20px"} !important;
1159
+ max-width: ${config?.maxWidth || "80%"} !important;
1160
+ ${config?.position === "top"
1161
+ ? "top: 10% !important; bottom: auto !important;"
1162
+ : ""}
1163
+ ${config?.position === "center"
1164
+ ? "top: 50% !important; bottom: auto !important; transform: translateX(-50%) translateY(-50%) !important;"
1165
+ : ""}
1166
+ ${config?.position === "bottom" || !config?.position
1167
+ ? "bottom: 15% !important; top: auto !important;"
1168
+ : ""}
1169
+ }
1170
+ `;
1171
+ style.textContent = styles;
1172
+ document.head.appendChild(style);
1173
+ };
1174
+ applySubtitleStyles();
1175
+ return () => {
1176
+ const existingStyle = document.getElementById("custom-subtitle-styles");
1177
+ if (existingStyle) {
1178
+ existingStyle.remove();
1179
+ }
1180
+ };
1181
+ }, [videoRef, config]);
1182
+ };
1183
+
1184
+ const useVideoTracking = (tracking, episodeList, currentEpisodeIndex, onClose) => {
1185
+ const { videoRef, setIsPlaying, setShowCountdown } = useVideoStore();
855
1186
  const startTime = useRef(null);
856
1187
  const isViewCounted = useRef(false);
857
1188
  useEffect(() => {
@@ -898,43 +1229,43 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
898
1229
  videoRef.removeEventListener("pause", onPause);
899
1230
  videoRef.removeEventListener("ended", onEnded);
900
1231
  };
901
- }, [videoRef, episodeList, currentEpisodeIndex, onClose]);
902
- // === BEFORE UNLOAD ===
903
- const handleUnload = (e) => {
904
- e.preventDefault();
905
- if (startTime.current) {
906
- const elapsedTime = (Date.now() - startTime.current) / 1000;
907
- const getCurrentTime = localStorage.getItem("current_time");
908
- localStorage.setItem("current_time", (Number(getCurrentTime || 0) + elapsedTime).toString());
909
- }
910
- const totalTimeWatched = Number(localStorage.getItem("current_time") || 0);
911
- if (totalTimeWatched >= 30) {
912
- tracking?.onWatchTimeUpdated?.({
913
- watchTime: totalTimeWatched,
914
- });
915
- }
916
- localStorage.setItem("current_time", "0");
917
- };
1232
+ }, [
1233
+ videoRef,
1234
+ episodeList,
1235
+ currentEpisodeIndex,
1236
+ onClose,
1237
+ tracking,
1238
+ setIsPlaying,
1239
+ setShowCountdown,
1240
+ ]);
918
1241
  useEffect(() => {
1242
+ const handleUnload = (e) => {
1243
+ e.preventDefault();
1244
+ if (startTime.current) {
1245
+ const elapsedTime = (Date.now() - startTime.current) / 1000;
1246
+ const getCurrentTime = localStorage.getItem("current_time");
1247
+ localStorage.setItem("current_time", (Number(getCurrentTime || 0) + elapsedTime).toString());
1248
+ }
1249
+ const totalTimeWatched = Number(localStorage.getItem("current_time") || 0);
1250
+ if (totalTimeWatched >= 30) {
1251
+ tracking?.onWatchTimeUpdated?.({
1252
+ watchTime: totalTimeWatched,
1253
+ });
1254
+ }
1255
+ localStorage.setItem("current_time", "0");
1256
+ };
919
1257
  window.addEventListener("beforeunload", handleUnload);
920
1258
  window.addEventListener("unload", handleUnload);
921
1259
  return () => {
922
1260
  window.removeEventListener("beforeunload", handleUnload);
923
1261
  window.removeEventListener("unload", handleUnload);
924
1262
  };
925
- }, [startTime]);
926
- useEffect(() => {
927
- if (subtitles) {
928
- setSubtitles(subtitles);
929
- }
930
- if (episodeList) {
931
- setEpisodeList(episodeList);
932
- }
933
- if (currentEpisodeIndex !== undefined) {
934
- setCurrentEpisodeIndex(currentEpisodeIndex);
935
- }
936
- }, [subtitles, episodeList, currentEpisodeIndex]);
937
- // === INTRO LOGIC ===
1263
+ }, [tracking]);
1264
+ };
1265
+
1266
+ const useIntroSkip = (intro) => {
1267
+ const { videoRef } = useVideoStore();
1268
+ const [showSkipIntro, setShowSkipIntro] = useState(false);
938
1269
  useEffect(() => {
939
1270
  if (!videoRef || !intro)
940
1271
  return;
@@ -958,13 +1289,32 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
958
1289
  setShowSkipIntro(false);
959
1290
  }
960
1291
  };
961
- // === NEXT EPISODE LOGIC (Backend Dependent) ===
1292
+ return {
1293
+ showSkipIntro,
1294
+ handleSkipIntro,
1295
+ };
1296
+ };
1297
+
1298
+ const useEpisodes = (episodeList, currentEpisodeIndex, nextEpisodeConfig) => {
1299
+ const { videoRef, setEpisodeList, setCurrentEpisodeIndex, setShowCountdown } = useVideoStore();
1300
+ useEffect(() => {
1301
+ if (episodeList) {
1302
+ setEpisodeList(episodeList);
1303
+ }
1304
+ if (currentEpisodeIndex !== undefined) {
1305
+ setCurrentEpisodeIndex(currentEpisodeIndex);
1306
+ }
1307
+ }, [
1308
+ episodeList,
1309
+ currentEpisodeIndex,
1310
+ setEpisodeList,
1311
+ setCurrentEpisodeIndex,
1312
+ ]);
962
1313
  useEffect(() => {
963
1314
  if (!videoRef || !nextEpisodeConfig)
964
1315
  return;
965
1316
  const checkNextEpisode = () => {
966
1317
  const currentTime = videoRef.currentTime || 0;
967
- // Show based on backend config
968
1318
  if (nextEpisodeConfig.showAtEnd && videoRef.ended) {
969
1319
  setShowCountdown(true);
970
1320
  }
@@ -979,29 +1329,86 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
979
1329
  videoRef.removeEventListener("timeupdate", checkNextEpisode);
980
1330
  videoRef.removeEventListener("ended", checkNextEpisode);
981
1331
  };
982
- }, [videoRef, nextEpisodeConfig]);
983
- return (React__default.createElement("div", { ref: setVideoWrapperRef, className: `${height || "h-full"} ${width || "w-full"} mx-auto absolute` },
984
- React__default.createElement("video", { ref: setVideoRef, className: `w-full h-full relative ${className} [&::cue]:absolute
985
- [&::cue]:top-[6%]
986
- [&::cue]:text-xl
987
- [&::cue]:bg-gray-50
988
- [&::cue]:text-[#1E1E1E]
989
- [&::cue]:px-2
990
- [&::cue]:py-1
991
- [&::cue]:rounded-md`, poster: trackPoster, autoPlay: true, crossOrigin: "anonymous", onContextMenu: onRightClick, playsInline: true, preload: "auto", onSeeked: (e) => {
992
- if (e?.currentTarget?.currentTime) {
993
- setCurrentTime(e?.currentTarget?.currentTime);
994
- }
995
- }, onTimeUpdate: (e) => {
996
- if (e?.currentTarget?.currentTime) {
997
- setCurrentTime(e?.currentTarget?.currentTime);
998
- }
999
- }, onLoadedMetadata: (e) => {
1000
- if (e?.currentTarget?.duration) {
1001
- localStorage.setItem("current_time", "0");
1002
- setDuration(e?.currentTarget?.duration);
1332
+ }, [videoRef, nextEpisodeConfig, setShowCountdown]);
1333
+ };
1334
+
1335
+ const useVideoEvents = () => {
1336
+ const { setCurrentTime, setDuration, setBufferedProgress, setIsPlaying } = useVideoStore();
1337
+ const onRightClick = (e) => {
1338
+ e.preventDefault();
1339
+ };
1340
+ const onSeeked = (e) => {
1341
+ if (e?.currentTarget?.currentTime) {
1342
+ setCurrentTime(e?.currentTarget?.currentTime);
1343
+ }
1344
+ };
1345
+ const onTimeUpdate = (e) => {
1346
+ if (e?.currentTarget?.currentTime) {
1347
+ setCurrentTime(e?.currentTarget?.currentTime);
1348
+ }
1349
+ };
1350
+ const onLoadedMetadata = (e) => {
1351
+ if (e?.currentTarget?.duration) {
1352
+ localStorage.setItem("current_time", "0");
1353
+ setDuration(e?.currentTarget?.duration);
1354
+ }
1355
+ };
1356
+ const onProgress = (e) => {
1357
+ const video = e.currentTarget;
1358
+ if (video.buffered.length > 0 &&
1359
+ video.duration > 0 &&
1360
+ !isNaN(video.duration)) {
1361
+ let bufferedEnd = 0;
1362
+ for (let i = 0; i < video.buffered.length; i++) {
1363
+ if (video.currentTime >= video.buffered.start(i) &&
1364
+ video.currentTime <= video.buffered.end(i)) {
1365
+ bufferedEnd = video.buffered.end(i);
1366
+ break;
1003
1367
  }
1004
- } }),
1368
+ }
1369
+ if (bufferedEnd === 0 && video.buffered.length > 0) {
1370
+ bufferedEnd = video.buffered.end(video.buffered.length - 1);
1371
+ }
1372
+ const bufferedProgress = Math.min((bufferedEnd / video.duration) * 100, 100);
1373
+ setBufferedProgress(bufferedProgress);
1374
+ }
1375
+ };
1376
+ const onPlay = () => {
1377
+ setIsPlaying(true);
1378
+ };
1379
+ const onPause = () => {
1380
+ setIsPlaying(false);
1381
+ };
1382
+ const onEnded = () => {
1383
+ setIsPlaying(false);
1384
+ };
1385
+ return {
1386
+ onRightClick,
1387
+ onSeeked,
1388
+ onTimeUpdate,
1389
+ onLoadedMetadata,
1390
+ onProgress,
1391
+ onPlay,
1392
+ onPause,
1393
+ onEnded,
1394
+ };
1395
+ };
1396
+
1397
+ var css_248z = ".video-player video::cue {\n display: none !important;\n opacity: 0 !important;\n visibility: hidden !important;\n}\n\n.custom-subtitle-overlay {\n position: absolute;\n bottom: 10%;\n left: 50%;\n transform: translateX(-50%);\n\n font-size: 1.5rem;\n font-weight: 600;\n line-height: 1.4;\n text-align: center;\n\n color: #000;\n background: rgba(255, 255, 255, 0.6);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n\n padding: 10px 16px;\n border-radius: 10px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);\n\n max-width: 70%;\n min-width: fit-content;\n\n transition: all 0.2s ease-in-out;\n}\n\n.custom-subtitle-overlay:hover {\n transform: translateX(-50%) scale(1.02);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);\n}\n\n@media (max-width: 768px) {\n .custom-subtitle-overlay {\n font-size: 1.25rem;\n padding: 8px 14px;\n bottom: 8%;\n max-width: 85%;\n }\n}\n\n@media (max-width: 480px) {\n .custom-subtitle-overlay {\n font-size: 1rem;\n padding: 6px 10px;\n bottom: 6%;\n max-width: 90%;\n }\n}\n\n@media (prefers-contrast: high) {\n .custom-subtitle-overlay {\n background: #ffff00;\n color: #000;\n border: 3px solid #000;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-subtitle-overlay {\n transition: none;\n }\n\n .custom-subtitle-overlay:hover {\n transform: translateX(-50%);\n }\n}\n";
1398
+ styleInject(css_248z,{"insertAt":"top"});
1399
+
1400
+ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrailer, className, type, height, width, timeCodes, getPreviewScreenUrl, tracking, subtitles, episodeList, currentEpisodeIndex = 0, nextEpisodeConfig, subtitleStyle, }) => {
1401
+ const { setVideoRef, setVideoWrapperRef, videoRef } = useVideoStore();
1402
+ useVideoSource(trackSrc, type);
1403
+ useSubtitles(subtitles);
1404
+ useSubtitleStyling(subtitleStyle);
1405
+ useVideoTracking(tracking, episodeList, currentEpisodeIndex, onClose);
1406
+ const { showSkipIntro, handleSkipIntro } = useIntroSkip(intro);
1407
+ useEpisodes(episodeList, currentEpisodeIndex, nextEpisodeConfig);
1408
+ const { onSeeked, onTimeUpdate, onLoadedMetadata, onProgress, onPlay, onPause, onEnded } = useVideoEvents();
1409
+ return (React__default.createElement("div", { ref: setVideoWrapperRef, className: `video-player ${height || "h-full"} ${width || "w-full"} mx-auto absolute` },
1410
+ trackPoster && (React__default.createElement("div", { className: "pip-poster absolute inset-0 bg-center bg-cover hidden", style: { backgroundImage: `url(${trackPoster})` } })),
1411
+ React__default.createElement("video", { autoPlay: true, playsInline: true, preload: "metadata", ref: setVideoRef, onSeeked: onSeeked, poster: trackPoster, crossOrigin: "anonymous", controls: false, disableRemotePlayback: true, controlsList: "nodownload", onContextMenu: (e) => e.preventDefault(), onTimeUpdate: onTimeUpdate, onLoadedMetadata: onLoadedMetadata, onProgress: onProgress, onPlay: onPlay, onPause: onPause, onEnded: onEnded, className: `w-full h-full relative ${className}` }),
1005
1412
  React__default.createElement(Overlay, { config: {
1006
1413
  headerConfig: {
1007
1414
  config: {
@@ -1021,6 +1428,7 @@ const VideoPlayer = ({ trackSrc, trackTitle, intro, onClose, trackPoster, isTrai
1021
1428
  },
1022
1429
  },
1023
1430
  } }),
1431
+ React__default.createElement(SubtitleOverlay, { styleConfig: subtitleStyle }),
1024
1432
  showSkipIntro && (React__default.createElement(VideoActionButton, { text: "Skip Intro", onClick: handleSkipIntro, position: "left" }))));
1025
1433
  };
1026
1434