@geekapps/silo-elements-nextjs 0.2.69 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1245,6 +1245,7 @@ function Video({
1245
1245
  const containerRef = useRef(null);
1246
1246
  const chromeRef = useRef(null);
1247
1247
  const playerRef = useRef(null);
1248
+ const showAgeRatingRef = useRef(null);
1248
1249
  const videoRef = useRef(null);
1249
1250
  const progressRef = useRef(null);
1250
1251
  const hlsRef = useRef(null);
@@ -1257,7 +1258,6 @@ function Video({
1257
1258
  const [selectedAudio, setSelectedAudio] = useState(0);
1258
1259
  const [settingsOpen, setSettingsOpen] = useState(false);
1259
1260
  const [settingsVisible, setSettingsVisible] = useState(false);
1260
- const settingsCloseTimerRef = useRef(null);
1261
1261
  const [settingsTab, setSettingsTab] = useState("root");
1262
1262
  const [playbackRate, setPlaybackRate] = useState(1);
1263
1263
  const [subtitleStyle, setSubtitleStyle] = useState({
@@ -1305,12 +1305,20 @@ function Video({
1305
1305
  const dragPointerIdRef = useRef(null);
1306
1306
  const [isPlaying, setIsPlaying] = useState(false);
1307
1307
  const [hasPlayed, setHasPlayed] = useState(false);
1308
- const [ageRatingOverlay, setAgeRatingOverlay] = useState(false);
1309
- const ageRatingTimerRef = useRef(null);
1308
+ const ageRatingTlRef = useRef(null);
1309
+ const ageRatingPauseTimerRef = useRef(null);
1310
+ const ageRatingWrapRef = useRef(null);
1311
+ const ageRatingIconRef = useRef(null);
1312
+ const ageRatingTextRef = useRef(null);
1310
1313
  const [clickIcon, setClickIcon] = useState(null);
1311
1314
  const clickIconTimerRef = useRef(null);
1315
+ const clickIconRef = useRef(null);
1312
1316
  const [isLoading, setIsLoading] = useState(true);
1313
1317
  const [controlsVisible, setControlsVisible] = useState(true);
1318
+ const settingsPanelRef = useRef(null);
1319
+ const settingsContentRef = useRef(null);
1320
+ const progressTrackRef = useRef(null);
1321
+ const progressThumbRef = useRef(null);
1314
1322
  const [volume, setVolume] = useState(defaultVolume);
1315
1323
  const [isMuted, setIsMuted] = useState(false);
1316
1324
  const [isFullscreen, setIsFullscreen] = useState(false);
@@ -1376,6 +1384,9 @@ function Video({
1376
1384
  setControlsVisible(false);
1377
1385
  }, 2400);
1378
1386
  }
1387
+ if (video?.paused) {
1388
+ showAgeRatingRef.current?.();
1389
+ }
1379
1390
  }, [autoHideControls]);
1380
1391
  useEffect(() => {
1381
1392
  if (!containerRef.current) return;
@@ -1400,13 +1411,96 @@ function Video({
1400
1411
  const openSettings = useCallback(() => {
1401
1412
  setSettingsOpen(true);
1402
1413
  setSettingsTab("root");
1403
- window.setTimeout(() => setSettingsVisible(true), 10);
1414
+ setSettingsVisible(true);
1404
1415
  }, []);
1405
1416
  const closeSettings = useCallback(() => {
1406
- setSettingsVisible(false);
1407
- if (settingsCloseTimerRef.current) window.clearTimeout(settingsCloseTimerRef.current);
1408
- settingsCloseTimerRef.current = window.setTimeout(() => setSettingsOpen(false), 200);
1417
+ const panel = settingsPanelRef.current;
1418
+ if (panel) {
1419
+ gsap.killTweensOf(panel);
1420
+ gsap.to(panel, {
1421
+ opacity: 0,
1422
+ y: 8,
1423
+ scale: 0.97,
1424
+ duration: 0.18,
1425
+ ease: "power2.in",
1426
+ onComplete: () => {
1427
+ setSettingsOpen(false);
1428
+ setSettingsVisible(false);
1429
+ }
1430
+ });
1431
+ } else {
1432
+ setSettingsOpen(false);
1433
+ setSettingsVisible(false);
1434
+ }
1409
1435
  }, []);
1436
+ useEffect(() => {
1437
+ if (!settingsOpen) return;
1438
+ const panel = settingsPanelRef.current;
1439
+ if (!panel) return;
1440
+ gsap.killTweensOf(panel);
1441
+ gsap.fromTo(
1442
+ panel,
1443
+ { opacity: 0, y: 8, scale: 0.97 },
1444
+ { opacity: 1, y: 0, scale: 1, duration: 0.2, ease: "power2.out" }
1445
+ );
1446
+ }, [settingsOpen]);
1447
+ useEffect(() => {
1448
+ const el = settingsContentRef.current;
1449
+ if (!el) return;
1450
+ gsap.killTweensOf(el);
1451
+ gsap.fromTo(
1452
+ el,
1453
+ { opacity: 0, x: 12 },
1454
+ { opacity: 1, x: 0, duration: 0.18, ease: "power2.out" }
1455
+ );
1456
+ }, [settingsTab]);
1457
+ useEffect(() => {
1458
+ const el = chromeRef.current;
1459
+ const player = playerRef.current;
1460
+ if (!el) return;
1461
+ gsap.killTweensOf(el);
1462
+ gsap.to(el, {
1463
+ opacity: controlsVisible ? 1 : 0,
1464
+ duration: 0.2,
1465
+ ease: "power1.inOut"
1466
+ });
1467
+ el.style.pointerEvents = controlsVisible ? "" : "none";
1468
+ if (player) {
1469
+ player.style.cursor = controlsVisible ? "" : "none";
1470
+ }
1471
+ }, [controlsVisible]);
1472
+ useEffect(() => {
1473
+ const el = clickIconRef.current;
1474
+ if (!el) return;
1475
+ gsap.killTweensOf(el);
1476
+ if (clickIcon) {
1477
+ gsap.to(el, { opacity: 1, duration: 0.08, ease: "power1.in" });
1478
+ } else {
1479
+ gsap.to(el, { opacity: 0, duration: 0.45, ease: "power1.out" });
1480
+ }
1481
+ }, [clickIcon]);
1482
+ useEffect(() => {
1483
+ const track = progressTrackRef.current;
1484
+ const thumb = progressThumbRef.current;
1485
+ const container = progressRef.current;
1486
+ const targetH = isDragging ? 7 : isHoveringProgress ? 5 : 3;
1487
+ const targetW = isDragging ? 18 : isHoveringProgress ? 14 : 10;
1488
+ if (track) {
1489
+ gsap.killTweensOf(track);
1490
+ gsap.to(track, { height: targetH, duration: 0.15, ease: "power1.inOut" });
1491
+ }
1492
+ if (thumb) {
1493
+ gsap.killTweensOf(thumb);
1494
+ gsap.to(thumb, { width: targetW, height: targetW, duration: 0.2, ease: "back.out(1.7)" });
1495
+ }
1496
+ if (container) {
1497
+ const markers = container.querySelectorAll("[data-chapter-marker]");
1498
+ markers.forEach((el) => {
1499
+ gsap.killTweensOf(el);
1500
+ gsap.to(el, { height: targetH, duration: 0.15, ease: "power1.inOut" });
1501
+ });
1502
+ }
1503
+ }, [isDragging, isHoveringProgress]);
1410
1504
  useEffect(() => {
1411
1505
  if (sourceIndex >= parsed.sources.length) {
1412
1506
  setSourceIndex(initialSourceIndex);
@@ -1430,14 +1524,51 @@ function Video({
1430
1524
  setDuration(Number.isFinite(video.duration) ? video.duration : 0);
1431
1525
  applySubtitleMode(subtitleMode);
1432
1526
  };
1527
+ const hideAgeRating = () => {
1528
+ const wrap = ageRatingWrapRef.current;
1529
+ if (!wrap) return;
1530
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
1531
+ gsap.to(wrap, { opacity: 0, duration: 0.4, ease: "power2.inOut" });
1532
+ };
1533
+ const showAgeRating = () => {
1534
+ if (!parsed.ageRating?.data) return;
1535
+ const wrap = ageRatingWrapRef.current;
1536
+ const icon = ageRatingIconRef.current;
1537
+ const text = ageRatingTextRef.current;
1538
+ if (!wrap) return;
1539
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
1540
+ const HOLD = 12;
1541
+ const tl = gsap.timeline({ delay: 0.6 });
1542
+ tl.fromTo(wrap, { opacity: 0 }, { opacity: 1, duration: 0.5, ease: "power2.out" });
1543
+ if (icon) {
1544
+ tl.fromTo(
1545
+ icon,
1546
+ { opacity: 0, scale: 0.7 },
1547
+ { opacity: 1, scale: 1, duration: 0.55, ease: "back.out(1.6)" },
1548
+ "-=0.2"
1549
+ );
1550
+ }
1551
+ if (text) {
1552
+ tl.fromTo(
1553
+ text,
1554
+ { opacity: 0, x: -10 },
1555
+ { opacity: 1, x: 0, duration: 0.4, ease: "power2.out" },
1556
+ "-=0.25"
1557
+ );
1558
+ }
1559
+ tl.to({}, { duration: HOLD });
1560
+ tl.to(wrap, { opacity: 0, duration: 0.7, ease: "power2.inOut" });
1561
+ ageRatingTlRef.current = tl;
1562
+ };
1563
+ showAgeRatingRef.current = showAgeRating;
1433
1564
  const onPlay = () => {
1434
1565
  setIsPlaying(true);
1566
+ if (ageRatingPauseTimerRef.current) {
1567
+ window.clearTimeout(ageRatingPauseTimerRef.current);
1568
+ ageRatingPauseTimerRef.current = null;
1569
+ }
1435
1570
  setHasPlayed((prev) => {
1436
- if (!prev && parsed.ageRating?.data) {
1437
- setAgeRatingOverlay(true);
1438
- if (ageRatingTimerRef.current) window.clearTimeout(ageRatingTimerRef.current);
1439
- ageRatingTimerRef.current = window.setTimeout(() => setAgeRatingOverlay(false), 4e3);
1440
- }
1571
+ if (!prev) showAgeRating();
1441
1572
  return true;
1442
1573
  });
1443
1574
  showControlsTemporarily();
@@ -1445,6 +1576,14 @@ function Video({
1445
1576
  const onPause = () => {
1446
1577
  setIsPlaying(false);
1447
1578
  setControlsVisible(true);
1579
+ hideAgeRating();
1580
+ if (parsed.ageRating?.data) {
1581
+ if (ageRatingPauseTimerRef.current) window.clearTimeout(ageRatingPauseTimerRef.current);
1582
+ ageRatingPauseTimerRef.current = window.setTimeout(() => {
1583
+ showAgeRating();
1584
+ ageRatingPauseTimerRef.current = null;
1585
+ }, 60 * 1e3);
1586
+ }
1448
1587
  };
1449
1588
  const onWaiting = () => setIsLoading(true);
1450
1589
  const onCanPlay = () => setIsLoading(false);
@@ -1468,6 +1607,8 @@ function Video({
1468
1607
  video.removeEventListener("waiting", onWaiting);
1469
1608
  video.removeEventListener("canplay", onCanPlay);
1470
1609
  video.removeEventListener("ended", onEnded);
1610
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
1611
+ if (ageRatingPauseTimerRef.current) window.clearTimeout(ageRatingPauseTimerRef.current);
1471
1612
  };
1472
1613
  }, [applySubtitleMode, subtitleMode, showControlsTemporarily]);
1473
1614
  useEffect(() => {
@@ -2119,932 +2260,940 @@ function Video({
2119
2260
  "."
2120
2261
  ] });
2121
2262
  }
2122
- return /* @__PURE__ */ jsxs(
2263
+ return /* @__PURE__ */ jsx(
2123
2264
  "div",
2124
2265
  {
2125
2266
  ref: containerRef,
2126
2267
  className: `@container mx-auto w-full max-w-6xl${className ?? ""}`,
2127
- children: [
2128
- /* @__PURE__ */ jsx("style", { children: `@keyframes silo-fade-out{0%{opacity:1}70%{opacity:1}100%{opacity:0}}` }),
2129
- /* @__PURE__ */ jsxs(
2130
- "div",
2131
- {
2132
- ref: playerRef,
2133
- tabIndex: 0,
2134
- onKeyDown: handleKeyDown,
2135
- onMouseMove: showControlsTemporarily,
2136
- onMouseLeave: () => {
2268
+ children: /* @__PURE__ */ jsxs(
2269
+ "div",
2270
+ {
2271
+ ref: playerRef,
2272
+ tabIndex: 0,
2273
+ onKeyDown: handleKeyDown,
2274
+ onMouseMove: showControlsTemporarily,
2275
+ onMouseLeave: () => {
2276
+ closeSettings();
2277
+ if (isPlaying && autoHideControls) {
2278
+ setControlsVisible(false);
2279
+ }
2280
+ },
2281
+ onBlur: (e) => {
2282
+ if (!e.currentTarget.contains(e.relatedTarget)) {
2137
2283
  closeSettings();
2138
- if (isPlaying && autoHideControls) {
2139
- setControlsVisible(false);
2284
+ }
2285
+ },
2286
+ onTouchStart: showControlsTemporarily,
2287
+ onTouchMove: showControlsTemporarily,
2288
+ className: "relative w-full overflow-hidden rounded-[14px] bg-black shadow-[0_30px_90px_rgba(15,15,15,0.22)] outline-none ring-1 ring-black/5",
2289
+ style: fixedHeight ? {
2290
+ height: typeof fixedHeight === "number" ? `${fixedHeight}px` : fixedHeight
2291
+ } : maxHeight ? {
2292
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
2293
+ aspectRatio: "16/9"
2294
+ } : { aspectRatio: "16/9" },
2295
+ children: [
2296
+ /* @__PURE__ */ jsxs(
2297
+ "video",
2298
+ {
2299
+ ref: videoRef,
2300
+ className: `h-full w-full ${isFullscreen ? "object-contain" : "object-cover"}`,
2301
+ playsInline: true,
2302
+ preload: "metadata",
2303
+ crossOrigin: "anonymous",
2304
+ children: [
2305
+ captions.map((subtitle) => /* @__PURE__ */ jsx(
2306
+ "track",
2307
+ {
2308
+ kind: "subtitles",
2309
+ src: subtitle.src,
2310
+ srcLang: subtitle.srclang,
2311
+ label: subtitle.label,
2312
+ default: subtitle.default
2313
+ },
2314
+ `${activeSource.src}-${subtitle.srclang}-${subtitle.src}`
2315
+ )),
2316
+ parsed.storyboard?.src && /* @__PURE__ */ jsx(
2317
+ "track",
2318
+ {
2319
+ kind: "metadata",
2320
+ label: "thumbnails",
2321
+ src: parsed.storyboard.src
2322
+ }
2323
+ )
2324
+ ]
2140
2325
  }
2141
- },
2142
- onBlur: (e) => {
2143
- if (!e.currentTarget.contains(e.relatedTarget)) {
2144
- closeSettings();
2326
+ ),
2327
+ poster && !hasPlayed && /* @__PURE__ */ jsx(
2328
+ "img",
2329
+ {
2330
+ src: poster,
2331
+ "aria-hidden": true,
2332
+ className: "pointer-events-none absolute inset-0 h-full w-full object-contain bg-black"
2145
2333
  }
2146
- },
2147
- onTouchStart: showControlsTemporarily,
2148
- onTouchMove: showControlsTemporarily,
2149
- className: "relative w-full overflow-hidden rounded-[14px] bg-black shadow-[0_30px_90px_rgba(15,15,15,0.22)] outline-none ring-1 ring-black/5",
2150
- style: fixedHeight ? {
2151
- height: typeof fixedHeight === "number" ? `${fixedHeight}px` : fixedHeight
2152
- } : maxHeight ? {
2153
- maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
2154
- aspectRatio: "16/9"
2155
- } : { aspectRatio: "16/9" },
2156
- children: [
2157
- /* @__PURE__ */ jsxs(
2158
- "video",
2159
- {
2160
- ref: videoRef,
2161
- className: `h-full w-full ${isFullscreen ? "object-contain" : "object-cover"}`,
2162
- playsInline: true,
2163
- preload: "metadata",
2164
- crossOrigin: "anonymous",
2165
- children: [
2166
- captions.map((subtitle) => /* @__PURE__ */ jsx(
2167
- "track",
2168
- {
2169
- kind: "subtitles",
2170
- src: subtitle.src,
2171
- srcLang: subtitle.srclang,
2172
- label: subtitle.label,
2173
- default: subtitle.default
2174
- },
2175
- `${activeSource.src}-${subtitle.srclang}-${subtitle.src}`
2176
- )),
2177
- parsed.storyboard?.src && /* @__PURE__ */ jsx(
2178
- "track",
2179
- {
2180
- kind: "metadata",
2181
- label: "thumbnails",
2182
- src: parsed.storyboard.src
2183
- }
2184
- )
2185
- ]
2186
- }
2187
- ),
2188
- poster && !hasPlayed && /* @__PURE__ */ jsx(
2189
- "img",
2190
- {
2191
- src: poster,
2192
- "aria-hidden": true,
2193
- className: "pointer-events-none absolute inset-0 h-full w-full object-contain bg-black"
2194
- }
2195
- ),
2196
- ageRatingOverlay && parsed.ageRating?.data && (() => {
2197
- const ar = parsed.ageRating;
2198
- const regionKey = resolveAgeRatingRegion(ar.locale, ar.data);
2199
- if (!regionKey) return null;
2200
- const code = ar.data[regionKey];
2201
- const lookupKey = `${regionKey}:${code}`;
2202
- const info = ar.lookup?.[lookupKey];
2203
- return /* @__PURE__ */ jsx(
2204
- "div",
2205
- {
2206
- className: "pointer-events-none absolute inset-0 z-40 flex items-start justify-start p-4",
2207
- style: { animation: "silo-fade-out 4s forwards" },
2208
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 rounded-lg px-3 py-2", style: { background: "rgba(0,0,0,0.72)", backdropFilter: "blur(8px)" }, children: [
2209
- info?.imageUrl ? /* @__PURE__ */ jsx("img", { src: info.imageUrl, alt: code, className: "h-10 w-auto object-contain" }) : /* @__PURE__ */ jsx("span", { className: "flex h-10 min-w-10 items-center justify-center rounded border border-white/30 px-1.5 text-sm font-bold text-white", children: code }),
2210
- (info?.title || info?.description) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
2211
- info.title && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-white", children: info.title }),
2212
- info.description && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-white/60 leading-tight max-w-48", children: info.description })
2213
- ] })
2214
- ] })
2215
- }
2216
- );
2217
- })(),
2218
- /* @__PURE__ */ jsx(
2334
+ ),
2335
+ parsed.ageRating?.data && (() => {
2336
+ const ar = parsed.ageRating;
2337
+ const regionKey = resolveAgeRatingRegion(ar.locale, ar.data);
2338
+ if (!regionKey) return null;
2339
+ const code = ar.data[regionKey];
2340
+ const lookupKey = `${regionKey}:${code}`;
2341
+ const info = ar.lookup?.[lookupKey];
2342
+ return /* @__PURE__ */ jsx(
2219
2343
  "div",
2220
2344
  {
2221
- className: "pointer-events-none absolute inset-0 z-10 grid place-items-center",
2345
+ ref: ageRatingWrapRef,
2346
+ className: "pointer-events-none absolute inset-0 z-20 flex items-start justify-start",
2222
2347
  style: {
2223
- opacity: clickIcon ? 1 : 0,
2224
- transition: clickIcon ? "opacity 0.08s ease-in" : "opacity 0.45s ease-out"
2348
+ opacity: 0,
2349
+ background: "linear-gradient(135deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.4) 40%, transparent 65%)"
2225
2350
  },
2226
- children: /* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center text-white drop-shadow-[0_2px_12px_rgba(0,0,0,0.8)] @sm:size-14 @lg:size-16", children: clickIcon === "pause" ? /* @__PURE__ */ jsx(Pause, { className: "size-7 @sm:size-9 @lg:size-11", fill: "white" }) : /* @__PURE__ */ jsx(
2227
- Play,
2351
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3.5 px-5 pt-5 @sm:px-7 @sm:pt-7", children: [
2352
+ /* @__PURE__ */ jsx("div", { ref: ageRatingIconRef, style: { opacity: 0 }, children: info?.imageUrl ? /* @__PURE__ */ jsx("img", { src: info.imageUrl, alt: code, className: "h-14 w-auto object-contain @sm:h-16 drop-shadow-[0_2px_8px_rgba(0,0,0,0.6)]" }) : /* @__PURE__ */ jsx("span", { className: "flex h-14 min-w-14 items-center justify-center rounded-md border-2 border-white/40 px-2 text-lg font-bold text-white @sm:h-16 @sm:min-w-16 @sm:text-xl drop-shadow-[0_2px_8px_rgba(0,0,0,0.6)]", children: code }) }),
2353
+ (info?.title || info?.description) && /* @__PURE__ */ jsxs("div", { ref: ageRatingTextRef, className: "flex flex-col gap-0.5", style: { opacity: 0 }, children: [
2354
+ info.title && /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white @sm:text-base drop-shadow-[0_1px_4px_rgba(0,0,0,0.8)]", children: info.title }),
2355
+ info.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 leading-snug max-w-56 @sm:text-sm @sm:max-w-72 drop-shadow-[0_1px_4px_rgba(0,0,0,0.8)]", children: info.description })
2356
+ ] })
2357
+ ] })
2358
+ }
2359
+ );
2360
+ })(),
2361
+ /* @__PURE__ */ jsx(
2362
+ "div",
2363
+ {
2364
+ ref: clickIconRef,
2365
+ className: "pointer-events-none absolute inset-0 z-10 grid place-items-center",
2366
+ style: { opacity: 0 },
2367
+ children: /* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center text-white drop-shadow-[0_2px_12px_rgba(0,0,0,0.8)] @sm:size-14 @lg:size-16", children: clickIcon === "pause" ? /* @__PURE__ */ jsx(Pause, { className: "size-7 @sm:size-9 @lg:size-11", fill: "white" }) : /* @__PURE__ */ jsx(
2368
+ Play,
2369
+ {
2370
+ className: "ml-0.5 size-7 @sm:size-9 @lg:size-11",
2371
+ fill: "white"
2372
+ }
2373
+ ) })
2374
+ }
2375
+ ),
2376
+ isLoading && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-20 grid place-items-center bg-black/10", children: /* @__PURE__ */ jsx("div", { className: "size-9 animate-spin rounded-full border-2 border-white/25 border-t-white" }) }),
2377
+ /* @__PURE__ */ jsxs(
2378
+ "div",
2379
+ {
2380
+ ref: chromeRef,
2381
+ onClick: togglePlay,
2382
+ className: `absolute inset-0 z-30 flex flex-col ${isFullscreen ? "justify-between" : "justify-end"}`,
2383
+ children: [
2384
+ isFullscreen && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-black/70 to-transparent" }),
2385
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
2386
+ isFullscreen && /* @__PURE__ */ jsx(
2387
+ "header",
2228
2388
  {
2229
- className: "ml-0.5 size-7 @sm:size-9 @lg:size-11",
2230
- fill: "white"
2389
+ onClick: (e) => e.stopPropagation(),
2390
+ className: "relative z-10 flex items-start px-4 pt-4 text-white @sm:px-7 @sm:pt-7 @lg:px-9 @lg:pt-8",
2391
+ children: /* @__PURE__ */ jsxs("div", { children: [
2392
+ title && /* @__PURE__ */ jsx(
2393
+ "h1",
2394
+ {
2395
+ className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl",
2396
+ style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" },
2397
+ children: title
2398
+ }
2399
+ ),
2400
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
2401
+ ] })
2231
2402
  }
2232
- ) })
2233
- }
2234
- ),
2235
- isLoading && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-20 grid place-items-center bg-black/10", children: /* @__PURE__ */ jsx("div", { className: "size-9 animate-spin rounded-full border-2 border-white/25 border-t-white" }) }),
2236
- /* @__PURE__ */ jsxs(
2237
- "div",
2238
- {
2239
- ref: chromeRef,
2240
- onClick: togglePlay,
2241
- className: `absolute inset-0 z-30 flex flex-col transition-opacity duration-200 ${isFullscreen ? "justify-between" : "justify-end"} ${controlsVisible ? "opacity-100" : "opacity-0 pointer-events-none"}`,
2242
- children: [
2243
- isFullscreen && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-black/70 to-transparent" }),
2244
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
2245
- isFullscreen && /* @__PURE__ */ jsx(
2246
- "header",
2247
- {
2248
- onClick: (e) => e.stopPropagation(),
2249
- className: "relative z-10 flex items-start px-4 pt-4 text-white @sm:px-7 @sm:pt-7 @lg:px-9 @lg:pt-8",
2250
- children: /* @__PURE__ */ jsxs("div", { children: [
2251
- title && /* @__PURE__ */ jsx(
2252
- "h1",
2403
+ ),
2404
+ /* @__PURE__ */ jsxs(
2405
+ "footer",
2406
+ {
2407
+ onClick: (e) => e.stopPropagation(),
2408
+ className: "relative z-10 px-4 pb-4 text-white",
2409
+ children: [
2410
+ settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
2411
+ /* @__PURE__ */ jsx(
2412
+ "div",
2253
2413
  {
2254
- className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl",
2255
- style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" },
2256
- children: title
2414
+ className: "fixed inset-0 z-70",
2415
+ onClick: closeSettings
2257
2416
  }
2258
2417
  ),
2259
- description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
2260
- ] })
2261
- }
2262
- ),
2263
- /* @__PURE__ */ jsxs(
2264
- "footer",
2265
- {
2266
- onClick: (e) => e.stopPropagation(),
2267
- className: "relative z-10 px-4 pb-4 text-white",
2268
- children: [
2269
- settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
2270
- /* @__PURE__ */ jsx(
2271
- "div",
2272
- {
2273
- className: "fixed inset-0 z-70",
2274
- onClick: closeSettings
2275
- }
2276
- ),
2277
- /* @__PURE__ */ jsxs(
2278
- "div",
2279
- {
2280
- className: "absolute bottom-full right-2 z-70 mb-2 overflow-hidden rounded-2xl bg-[#1c1c1e]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/10",
2281
- style: {
2282
- width: Math.min(
2283
- 224,
2284
- Math.max(180, (playerWidth || 640) * 0.22)
2285
- ) + "px",
2286
- opacity: settingsVisible ? 1 : 0,
2287
- transform: settingsVisible ? "translateY(0) scale(1)" : "translateY(8px) scale(0.97)",
2288
- transition: "opacity 0.18s ease, transform 0.18s ease"
2289
- },
2290
- children: [
2291
- settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
2418
+ /* @__PURE__ */ jsx(
2419
+ "div",
2420
+ {
2421
+ ref: settingsPanelRef,
2422
+ className: "absolute bottom-full right-2 z-70 mb-2 overflow-hidden rounded-2xl bg-[#1c1c1e]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/10",
2423
+ style: {
2424
+ width: Math.min(
2425
+ 224,
2426
+ Math.max(180, (playerWidth || 640) * 0.22)
2427
+ ) + "px",
2428
+ opacity: 0
2429
+ },
2430
+ children: /* @__PURE__ */ jsxs("div", { ref: settingsContentRef, children: [
2431
+ settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
2432
+ {
2433
+ id: "quality",
2434
+ label: "Qualidade",
2435
+ value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto"
2436
+ },
2437
+ ...captions.length > 0 ? [
2438
+ {
2439
+ id: "subtitles",
2440
+ label: "Legendas",
2441
+ value: subtitleStyle.track === "off" ? "Desligado" : captions.find(
2442
+ (s) => s.srclang === subtitleStyle.track
2443
+ )?.label ?? subtitleStyle.track
2444
+ }
2445
+ ] : [],
2446
+ ...audioTracks.length > 1 ? [
2447
+ {
2448
+ id: "audio",
2449
+ label: "\xC1udio",
2450
+ value: audioTracks.find(
2451
+ (t) => t.id === selectedAudio
2452
+ )?.label ?? ""
2453
+ }
2454
+ ] : [],
2455
+ {
2456
+ id: "playback",
2457
+ label: "Velocidade",
2458
+ value: playbackRate === 1 ? "Normal" : `${playbackRate}\xD7`
2459
+ }
2460
+ ].map((item) => /* @__PURE__ */ jsxs(
2461
+ "button",
2462
+ {
2463
+ type: "button",
2464
+ onClick: () => setSettingsTab(item.id),
2465
+ className: "flex w-full items-center justify-between gap-3 px-4 py-3 text-sm transition hover:bg-white/8 first:pt-3.5 last:pb-3.5",
2466
+ children: [
2467
+ /* @__PURE__ */ jsx("span", { className: "text-white/80", children: item.label }),
2468
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-white/40", children: [
2469
+ item.value,
2470
+ /* @__PURE__ */ jsx(
2471
+ "svg",
2472
+ {
2473
+ className: "size-3 opacity-50",
2474
+ viewBox: "0 0 12 12",
2475
+ fill: "none",
2476
+ children: /* @__PURE__ */ jsx(
2477
+ "path",
2478
+ {
2479
+ d: "M4.5 3l3 3-3 3",
2480
+ stroke: "currentColor",
2481
+ strokeWidth: "1.5",
2482
+ strokeLinecap: "round",
2483
+ strokeLinejoin: "round"
2484
+ }
2485
+ )
2486
+ }
2487
+ )
2488
+ ] })
2489
+ ]
2490
+ },
2491
+ item.id
2492
+ )) }),
2493
+ settingsTab === "quality" && /* @__PURE__ */ jsxs("div", { children: [
2494
+ /* @__PURE__ */ jsxs(
2495
+ "button",
2292
2496
  {
2293
- id: "quality",
2294
- label: "Qualidade",
2295
- value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto"
2497
+ type: "button",
2498
+ onClick: () => setSettingsTab("root"),
2499
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2500
+ children: [
2501
+ /* @__PURE__ */ jsx(
2502
+ "svg",
2503
+ {
2504
+ className: "size-3.5",
2505
+ viewBox: "0 0 12 12",
2506
+ fill: "none",
2507
+ children: /* @__PURE__ */ jsx(
2508
+ "path",
2509
+ {
2510
+ d: "M7.5 3L4.5 6l3 3",
2511
+ stroke: "currentColor",
2512
+ strokeWidth: "1.5",
2513
+ strokeLinecap: "round",
2514
+ strokeLinejoin: "round"
2515
+ }
2516
+ )
2517
+ }
2518
+ ),
2519
+ "Qualidade"
2520
+ ]
2521
+ }
2522
+ ),
2523
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
2524
+ "button",
2525
+ {
2526
+ type: "button",
2527
+ onClick: () => {
2528
+ changeQuality(quality.id);
2529
+ setSettingsTab("root");
2530
+ },
2531
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2532
+ children: [
2533
+ /* @__PURE__ */ jsx(
2534
+ "svg",
2535
+ {
2536
+ className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`,
2537
+ viewBox: "0 0 16 16",
2538
+ fill: "none",
2539
+ children: /* @__PURE__ */ jsx(
2540
+ "path",
2541
+ {
2542
+ d: "M3 8l3.5 3.5L13 4.5",
2543
+ stroke: "currentColor",
2544
+ strokeWidth: "1.8",
2545
+ strokeLinecap: "round",
2546
+ strokeLinejoin: "round"
2547
+ }
2548
+ )
2549
+ }
2550
+ ),
2551
+ /* @__PURE__ */ jsxs(
2552
+ "span",
2553
+ {
2554
+ className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55",
2555
+ children: [
2556
+ quality.label,
2557
+ quality.id === "auto" ? " (ABR)" : ""
2558
+ ]
2559
+ }
2560
+ )
2561
+ ]
2296
2562
  },
2297
- ...captions.length > 0 ? [
2298
- {
2299
- id: "subtitles",
2300
- label: "Legendas",
2301
- value: subtitleStyle.track === "off" ? "Desligado" : captions.find(
2302
- (s) => s.srclang === subtitleStyle.track
2303
- )?.label ?? subtitleStyle.track
2304
- }
2305
- ] : [],
2306
- ...audioTracks.length > 1 ? [
2307
- {
2308
- id: "audio",
2309
- label: "\xC1udio",
2310
- value: audioTracks.find(
2311
- (t) => t.id === selectedAudio
2312
- )?.label ?? ""
2313
- }
2314
- ] : [],
2563
+ quality.id
2564
+ )) })
2565
+ ] }),
2566
+ settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
2567
+ /* @__PURE__ */ jsxs(
2568
+ "button",
2315
2569
  {
2316
- id: "playback",
2317
- label: "Velocidade",
2318
- value: playbackRate === 1 ? "Normal" : `${playbackRate}\xD7`
2570
+ type: "button",
2571
+ onClick: () => setSettingsTab("root"),
2572
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2573
+ children: [
2574
+ /* @__PURE__ */ jsx(
2575
+ "svg",
2576
+ {
2577
+ className: "size-3.5",
2578
+ viewBox: "0 0 12 12",
2579
+ fill: "none",
2580
+ children: /* @__PURE__ */ jsx(
2581
+ "path",
2582
+ {
2583
+ d: "M7.5 3L4.5 6l3 3",
2584
+ stroke: "currentColor",
2585
+ strokeWidth: "1.5",
2586
+ strokeLinecap: "round",
2587
+ strokeLinejoin: "round"
2588
+ }
2589
+ )
2590
+ }
2591
+ ),
2592
+ "Legendas"
2593
+ ]
2319
2594
  }
2320
- ].map((item) => /* @__PURE__ */ jsxs(
2595
+ ),
2596
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [
2597
+ { srclang: "off", label: "Desligado" },
2598
+ ...captions
2599
+ ].map((s) => /* @__PURE__ */ jsxs(
2321
2600
  "button",
2322
2601
  {
2323
2602
  type: "button",
2324
- onClick: () => setSettingsTab(item.id),
2325
- className: "flex w-full items-center justify-between gap-3 px-4 py-3 text-sm transition hover:bg-white/8 first:pt-3.5 last:pb-3.5",
2603
+ onClick: () => {
2604
+ const next = s.srclang === "off" ? "off" : s.srclang;
2605
+ setSubtitleMode(next);
2606
+ setSubtitleStyle((st) => ({
2607
+ ...st,
2608
+ track: next
2609
+ }));
2610
+ },
2611
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2326
2612
  children: [
2327
- /* @__PURE__ */ jsx("span", { className: "text-white/80", children: item.label }),
2328
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-white/40", children: [
2329
- item.value,
2330
- /* @__PURE__ */ jsx(
2331
- "svg",
2332
- {
2333
- className: "size-3 opacity-50",
2334
- viewBox: "0 0 12 12",
2335
- fill: "none",
2336
- children: /* @__PURE__ */ jsx(
2337
- "path",
2338
- {
2339
- d: "M4.5 3l3 3-3 3",
2340
- stroke: "currentColor",
2341
- strokeWidth: "1.5",
2342
- strokeLinecap: "round",
2343
- strokeLinejoin: "round"
2344
- }
2345
- )
2346
- }
2347
- )
2348
- ] })
2613
+ /* @__PURE__ */ jsx(
2614
+ "svg",
2615
+ {
2616
+ className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`,
2617
+ viewBox: "0 0 16 16",
2618
+ fill: "none",
2619
+ children: /* @__PURE__ */ jsx(
2620
+ "path",
2621
+ {
2622
+ d: "M3 8l3.5 3.5L13 4.5",
2623
+ stroke: "currentColor",
2624
+ strokeWidth: "1.8",
2625
+ strokeLinecap: "round",
2626
+ strokeLinejoin: "round"
2627
+ }
2628
+ )
2629
+ }
2630
+ ),
2631
+ /* @__PURE__ */ jsx(
2632
+ "span",
2633
+ {
2634
+ className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55",
2635
+ children: s.label
2636
+ }
2637
+ )
2349
2638
  ]
2350
2639
  },
2351
- item.id
2640
+ s.srclang
2352
2641
  )) }),
2353
- settingsTab === "quality" && /* @__PURE__ */ jsxs("div", { children: [
2354
- /* @__PURE__ */ jsxs(
2355
- "button",
2356
- {
2357
- type: "button",
2358
- onClick: () => setSettingsTab("root"),
2359
- className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2360
- children: [
2361
- /* @__PURE__ */ jsx(
2362
- "svg",
2363
- {
2364
- className: "size-3.5",
2365
- viewBox: "0 0 12 12",
2366
- fill: "none",
2367
- children: /* @__PURE__ */ jsx(
2368
- "path",
2369
- {
2370
- d: "M7.5 3L4.5 6l3 3",
2371
- stroke: "currentColor",
2372
- strokeWidth: "1.5",
2373
- strokeLinecap: "round",
2374
- strokeLinejoin: "round"
2375
- }
2376
- )
2377
- }
2378
- ),
2379
- "Qualidade"
2380
- ]
2381
- }
2382
- ),
2383
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
2384
- "button",
2385
- {
2386
- type: "button",
2387
- onClick: () => {
2388
- changeQuality(quality.id);
2389
- setSettingsTab("root");
2642
+ subtitleStyle.track !== "off" && /* @__PURE__ */ jsxs(
2643
+ "button",
2644
+ {
2645
+ type: "button",
2646
+ onClick: () => setSettingsTab("subtitles-style"),
2647
+ className: "flex w-full items-center justify-between gap-3 border-t border-white/8 px-4 py-3 text-sm transition hover:bg-white/8",
2648
+ children: [
2649
+ /* @__PURE__ */ jsx("span", { className: "text-white/60", children: "Apar\xEAncia" }),
2650
+ /* @__PURE__ */ jsx(
2651
+ "svg",
2652
+ {
2653
+ className: "size-3 opacity-50",
2654
+ viewBox: "0 0 12 12",
2655
+ fill: "none",
2656
+ children: /* @__PURE__ */ jsx(
2657
+ "path",
2658
+ {
2659
+ d: "M4.5 3l3 3-3 3",
2660
+ stroke: "currentColor",
2661
+ strokeWidth: "1.5",
2662
+ strokeLinecap: "round",
2663
+ strokeLinejoin: "round"
2664
+ }
2665
+ )
2666
+ }
2667
+ )
2668
+ ]
2669
+ }
2670
+ )
2671
+ ] }),
2672
+ settingsTab === "subtitles-style" && /* @__PURE__ */ jsxs("div", { children: [
2673
+ /* @__PURE__ */ jsxs(
2674
+ "button",
2675
+ {
2676
+ type: "button",
2677
+ onClick: () => setSettingsTab("subtitles"),
2678
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2679
+ children: [
2680
+ /* @__PURE__ */ jsx(
2681
+ "svg",
2682
+ {
2683
+ className: "size-3.5",
2684
+ viewBox: "0 0 12 12",
2685
+ fill: "none",
2686
+ children: /* @__PURE__ */ jsx(
2687
+ "path",
2688
+ {
2689
+ d: "M7.5 3L4.5 6l3 3",
2690
+ stroke: "currentColor",
2691
+ strokeWidth: "1.5",
2692
+ strokeLinecap: "round",
2693
+ strokeLinejoin: "round"
2694
+ }
2695
+ )
2696
+ }
2697
+ ),
2698
+ "Apar\xEAncia"
2699
+ ]
2700
+ }
2701
+ ),
2702
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex flex-col gap-3", children: [
2703
+ /* @__PURE__ */ jsxs("div", { children: [
2704
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Tamanho" }),
2705
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
2706
+ "button",
2707
+ {
2708
+ type: "button",
2709
+ onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
2710
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition${subtitleStyle.size === s ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
2711
+ children: s === "small" ? "P" : s === "medium" ? "M" : s === "large" ? "G" : "GG"
2390
2712
  },
2391
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2392
- children: [
2393
- /* @__PURE__ */ jsx(
2394
- "svg",
2395
- {
2396
- className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`,
2397
- viewBox: "0 0 16 16",
2398
- fill: "none",
2399
- children: /* @__PURE__ */ jsx(
2400
- "path",
2401
- {
2402
- d: "M3 8l3.5 3.5L13 4.5",
2403
- stroke: "currentColor",
2404
- strokeWidth: "1.8",
2405
- strokeLinecap: "round",
2406
- strokeLinejoin: "round"
2407
- }
2408
- )
2409
- }
2410
- ),
2411
- /* @__PURE__ */ jsxs(
2412
- "span",
2413
- {
2414
- className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55",
2415
- children: [
2416
- quality.label,
2417
- quality.id === "auto" ? " (ABR)" : ""
2418
- ]
2419
- }
2420
- )
2421
- ]
2422
- },
2423
- quality.id
2424
- )) })
2425
- ] }),
2426
- settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
2427
- /* @__PURE__ */ jsxs(
2428
- "button",
2429
- {
2430
- type: "button",
2431
- onClick: () => setSettingsTab("root"),
2432
- className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2433
- children: [
2434
- /* @__PURE__ */ jsx(
2435
- "svg",
2436
- {
2437
- className: "size-3.5",
2438
- viewBox: "0 0 12 12",
2439
- fill: "none",
2440
- children: /* @__PURE__ */ jsx(
2441
- "path",
2442
- {
2443
- d: "M7.5 3L4.5 6l3 3",
2444
- stroke: "currentColor",
2445
- strokeWidth: "1.5",
2446
- strokeLinecap: "round",
2447
- strokeLinejoin: "round"
2448
- }
2449
- )
2450
- }
2451
- ),
2452
- "Legendas"
2453
- ]
2454
- }
2455
- ),
2456
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [
2457
- { srclang: "off", label: "Desligado" },
2458
- ...captions
2459
- ].map((s) => /* @__PURE__ */ jsxs(
2460
- "button",
2461
- {
2462
- type: "button",
2463
- onClick: () => {
2464
- const next = s.srclang === "off" ? "off" : s.srclang;
2465
- setSubtitleMode(next);
2466
- setSubtitleStyle((st) => ({
2713
+ s
2714
+ )) })
2715
+ ] }),
2716
+ /* @__PURE__ */ jsxs("div", { children: [
2717
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Cor" }),
2718
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
2719
+ ["white", "Branco", "#fff"],
2720
+ ["yellow", "Amarelo", "#facc15"],
2721
+ ["cyan", "Ciano", "#22d3ee"]
2722
+ ].map(([val, label, color]) => /* @__PURE__ */ jsx(
2723
+ "button",
2724
+ {
2725
+ type: "button",
2726
+ onClick: () => setSubtitleStyle((st) => ({
2467
2727
  ...st,
2468
- track: next
2469
- }));
2728
+ color: val
2729
+ })),
2730
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition ring-1${subtitleStyle.color === val ? "ring-white/40" : "ring-transparent hover:ring-white/15"}`,
2731
+ style: { color },
2732
+ children: label
2470
2733
  },
2471
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2472
- children: [
2473
- /* @__PURE__ */ jsx(
2474
- "svg",
2475
- {
2476
- className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`,
2477
- viewBox: "0 0 16 16",
2478
- fill: "none",
2479
- children: /* @__PURE__ */ jsx(
2480
- "path",
2481
- {
2482
- d: "M3 8l3.5 3.5L13 4.5",
2483
- stroke: "currentColor",
2484
- strokeWidth: "1.8",
2485
- strokeLinecap: "round",
2486
- strokeLinejoin: "round"
2487
- }
2488
- )
2489
- }
2490
- ),
2491
- /* @__PURE__ */ jsx(
2492
- "span",
2493
- {
2494
- className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55",
2495
- children: s.label
2496
- }
2497
- )
2498
- ]
2734
+ val
2735
+ )) })
2736
+ ] }),
2737
+ /* @__PURE__ */ jsxs("div", { children: [
2738
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Fundo" }),
2739
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
2740
+ ["none", "Nenhum"],
2741
+ ["semi", "Semi"],
2742
+ ["solid", "S\xF3lido"]
2743
+ ].map(([val, label]) => /* @__PURE__ */ jsx(
2744
+ "button",
2745
+ {
2746
+ type: "button",
2747
+ onClick: () => setSubtitleStyle((st) => ({ ...st, bg: val })),
2748
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition${subtitleStyle.bg === val ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
2749
+ children: label
2750
+ },
2751
+ val
2752
+ )) })
2753
+ ] })
2754
+ ] })
2755
+ ] }),
2756
+ settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
2757
+ /* @__PURE__ */ jsxs(
2758
+ "button",
2759
+ {
2760
+ type: "button",
2761
+ onClick: () => setSettingsTab("root"),
2762
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2763
+ children: [
2764
+ /* @__PURE__ */ jsx(
2765
+ "svg",
2766
+ {
2767
+ className: "size-3.5",
2768
+ viewBox: "0 0 12 12",
2769
+ fill: "none",
2770
+ children: /* @__PURE__ */ jsx(
2771
+ "path",
2772
+ {
2773
+ d: "M7.5 3L4.5 6l3 3",
2774
+ stroke: "currentColor",
2775
+ strokeWidth: "1.5",
2776
+ strokeLinecap: "round",
2777
+ strokeLinejoin: "round"
2778
+ }
2779
+ )
2780
+ }
2781
+ ),
2782
+ "\xC1udio"
2783
+ ]
2784
+ }
2785
+ ),
2786
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
2787
+ "button",
2788
+ {
2789
+ type: "button",
2790
+ onClick: () => {
2791
+ changeAudio(track.id);
2792
+ setSettingsTab("root");
2499
2793
  },
2500
- s.srclang
2501
- )) }),
2502
- subtitleStyle.track !== "off" && /* @__PURE__ */ jsxs(
2503
- "button",
2504
- {
2505
- type: "button",
2506
- onClick: () => setSettingsTab("subtitles-style"),
2507
- className: "flex w-full items-center justify-between gap-3 border-t border-white/8 px-4 py-3 text-sm transition hover:bg-white/8",
2508
- children: [
2509
- /* @__PURE__ */ jsx("span", { className: "text-white/60", children: "Apar\xEAncia" }),
2510
- /* @__PURE__ */ jsx(
2511
- "svg",
2512
- {
2513
- className: "size-3 opacity-50",
2514
- viewBox: "0 0 12 12",
2515
- fill: "none",
2516
- children: /* @__PURE__ */ jsx(
2517
- "path",
2518
- {
2519
- d: "M4.5 3l3 3-3 3",
2520
- stroke: "currentColor",
2521
- strokeWidth: "1.5",
2522
- strokeLinecap: "round",
2523
- strokeLinejoin: "round"
2524
- }
2525
- )
2526
- }
2527
- )
2528
- ]
2529
- }
2530
- )
2531
- ] }),
2532
- settingsTab === "subtitles-style" && /* @__PURE__ */ jsxs("div", { children: [
2533
- /* @__PURE__ */ jsxs(
2534
- "button",
2535
- {
2536
- type: "button",
2537
- onClick: () => setSettingsTab("subtitles"),
2538
- className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2539
- children: [
2540
- /* @__PURE__ */ jsx(
2541
- "svg",
2542
- {
2543
- className: "size-3.5",
2544
- viewBox: "0 0 12 12",
2545
- fill: "none",
2546
- children: /* @__PURE__ */ jsx(
2547
- "path",
2548
- {
2549
- d: "M7.5 3L4.5 6l3 3",
2550
- stroke: "currentColor",
2551
- strokeWidth: "1.5",
2552
- strokeLinecap: "round",
2553
- strokeLinejoin: "round"
2554
- }
2555
- )
2556
- }
2557
- ),
2558
- "Apar\xEAncia"
2559
- ]
2560
- }
2561
- ),
2562
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex flex-col gap-3", children: [
2563
- /* @__PURE__ */ jsxs("div", { children: [
2564
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Tamanho" }),
2565
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
2566
- "button",
2794
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2795
+ children: [
2796
+ /* @__PURE__ */ jsx(
2797
+ "svg",
2567
2798
  {
2568
- type: "button",
2569
- onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
2570
- className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition${subtitleStyle.size === s ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
2571
- children: s === "small" ? "P" : s === "medium" ? "M" : s === "large" ? "G" : "GG"
2572
- },
2573
- s
2574
- )) })
2575
- ] }),
2576
- /* @__PURE__ */ jsxs("div", { children: [
2577
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Cor" }),
2578
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
2579
- ["white", "Branco", "#fff"],
2580
- ["yellow", "Amarelo", "#facc15"],
2581
- ["cyan", "Ciano", "#22d3ee"]
2582
- ].map(([val, label, color]) => /* @__PURE__ */ jsx(
2583
- "button",
2799
+ className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`,
2800
+ viewBox: "0 0 16 16",
2801
+ fill: "none",
2802
+ children: /* @__PURE__ */ jsx(
2803
+ "path",
2804
+ {
2805
+ d: "M3 8l3.5 3.5L13 4.5",
2806
+ stroke: "currentColor",
2807
+ strokeWidth: "1.8",
2808
+ strokeLinecap: "round",
2809
+ strokeLinejoin: "round"
2810
+ }
2811
+ )
2812
+ }
2813
+ ),
2814
+ /* @__PURE__ */ jsx(
2815
+ "span",
2584
2816
  {
2585
- type: "button",
2586
- onClick: () => setSubtitleStyle((st) => ({
2587
- ...st,
2588
- color: val
2589
- })),
2590
- className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition ring-1${subtitleStyle.color === val ? "ring-white/40" : "ring-transparent hover:ring-white/15"}`,
2591
- style: { color },
2592
- children: label
2593
- },
2594
- val
2595
- )) })
2596
- ] }),
2597
- /* @__PURE__ */ jsxs("div", { children: [
2598
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Fundo" }),
2599
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
2600
- ["none", "Nenhum"],
2601
- ["semi", "Semi"],
2602
- ["solid", "S\xF3lido"]
2603
- ].map(([val, label]) => /* @__PURE__ */ jsx(
2604
- "button",
2817
+ className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55",
2818
+ children: track.label
2819
+ }
2820
+ )
2821
+ ]
2822
+ },
2823
+ track.id
2824
+ )) })
2825
+ ] }),
2826
+ settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
2827
+ /* @__PURE__ */ jsxs(
2828
+ "button",
2829
+ {
2830
+ type: "button",
2831
+ onClick: () => setSettingsTab("root"),
2832
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2833
+ children: [
2834
+ /* @__PURE__ */ jsx(
2835
+ "svg",
2605
2836
  {
2606
- type: "button",
2607
- onClick: () => setSubtitleStyle((st) => ({ ...st, bg: val })),
2608
- className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition${subtitleStyle.bg === val ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
2609
- children: label
2610
- },
2611
- val
2612
- )) })
2613
- ] })
2614
- ] })
2615
- ] }),
2616
- settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
2617
- /* @__PURE__ */ jsxs(
2618
- "button",
2619
- {
2620
- type: "button",
2621
- onClick: () => setSettingsTab("root"),
2622
- className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2623
- children: [
2624
- /* @__PURE__ */ jsx(
2625
- "svg",
2626
- {
2627
- className: "size-3.5",
2628
- viewBox: "0 0 12 12",
2629
- fill: "none",
2630
- children: /* @__PURE__ */ jsx(
2631
- "path",
2632
- {
2633
- d: "M7.5 3L4.5 6l3 3",
2634
- stroke: "currentColor",
2635
- strokeWidth: "1.5",
2636
- strokeLinecap: "round",
2637
- strokeLinejoin: "round"
2638
- }
2639
- )
2640
- }
2641
- ),
2642
- "\xC1udio"
2643
- ]
2644
- }
2645
- ),
2646
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
2647
- "button",
2648
- {
2649
- type: "button",
2650
- onClick: () => {
2651
- changeAudio(track.id);
2652
- setSettingsTab("root");
2653
- },
2654
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2655
- children: [
2656
- /* @__PURE__ */ jsx(
2657
- "svg",
2658
- {
2659
- className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`,
2660
- viewBox: "0 0 16 16",
2661
- fill: "none",
2662
- children: /* @__PURE__ */ jsx(
2663
- "path",
2664
- {
2665
- d: "M3 8l3.5 3.5L13 4.5",
2666
- stroke: "currentColor",
2667
- strokeWidth: "1.8",
2668
- strokeLinecap: "round",
2669
- strokeLinejoin: "round"
2670
- }
2671
- )
2672
- }
2673
- ),
2674
- /* @__PURE__ */ jsx(
2675
- "span",
2676
- {
2677
- className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55",
2678
- children: track.label
2679
- }
2680
- )
2681
- ]
2837
+ className: "size-3.5",
2838
+ viewBox: "0 0 12 12",
2839
+ fill: "none",
2840
+ children: /* @__PURE__ */ jsx(
2841
+ "path",
2842
+ {
2843
+ d: "M7.5 3L4.5 6l3 3",
2844
+ stroke: "currentColor",
2845
+ strokeWidth: "1.5",
2846
+ strokeLinecap: "round",
2847
+ strokeLinejoin: "round"
2848
+ }
2849
+ )
2850
+ }
2851
+ ),
2852
+ "Velocidade"
2853
+ ]
2854
+ }
2855
+ ),
2856
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsxs(
2857
+ "button",
2858
+ {
2859
+ type: "button",
2860
+ onClick: () => {
2861
+ setPlaybackRate(speed);
2862
+ closeSettings();
2682
2863
  },
2683
- track.id
2684
- )) })
2685
- ] }),
2686
- settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
2687
- /* @__PURE__ */ jsxs(
2688
- "button",
2864
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2865
+ children: [
2866
+ /* @__PURE__ */ jsx(
2867
+ "svg",
2868
+ {
2869
+ className: `size-4 shrink-0 ${playbackRate === speed ? "text-white" : "text-transparent"}`,
2870
+ viewBox: "0 0 16 16",
2871
+ fill: "none",
2872
+ children: /* @__PURE__ */ jsx(
2873
+ "path",
2874
+ {
2875
+ d: "M3 8l3.5 3.5L13 4.5",
2876
+ stroke: "currentColor",
2877
+ strokeWidth: "1.8",
2878
+ strokeLinecap: "round",
2879
+ strokeLinejoin: "round"
2880
+ }
2881
+ )
2882
+ }
2883
+ ),
2884
+ /* @__PURE__ */ jsx(
2885
+ "span",
2886
+ {
2887
+ className: playbackRate === speed ? "font-semibold text-white" : "text-white/55",
2888
+ children: speed === 1 ? "Normal" : `${speed}\xD7`
2889
+ }
2890
+ )
2891
+ ]
2892
+ },
2893
+ speed
2894
+ )) })
2895
+ ] })
2896
+ ] })
2897
+ }
2898
+ )
2899
+ ] }),
2900
+ /* @__PURE__ */ jsxs(
2901
+ "div",
2902
+ {
2903
+ ref: progressRef,
2904
+ onPointerMove: handleProgressPointerMove,
2905
+ onPointerEnter: handleProgressPointerEnter,
2906
+ onPointerLeave: handleProgressPointerLeave,
2907
+ onPointerDown: handleProgressPointerDown,
2908
+ onPointerUp: handleProgressPointerUp,
2909
+ className: "relative mb-2 h-8 cursor-pointer overflow-visible",
2910
+ children: [
2911
+ /* @__PURE__ */ jsxs(
2912
+ "div",
2913
+ {
2914
+ ref: progressTrackRef,
2915
+ className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/18",
2916
+ style: {
2917
+ height: "3px"
2918
+ },
2919
+ children: [
2920
+ /* @__PURE__ */ jsx(
2921
+ "div",
2689
2922
  {
2690
- type: "button",
2691
- onClick: () => setSettingsTab("root"),
2692
- className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
2693
- children: [
2694
- /* @__PURE__ */ jsx(
2695
- "svg",
2696
- {
2697
- className: "size-3.5",
2698
- viewBox: "0 0 12 12",
2699
- fill: "none",
2700
- children: /* @__PURE__ */ jsx(
2701
- "path",
2702
- {
2703
- d: "M7.5 3L4.5 6l3 3",
2704
- stroke: "currentColor",
2705
- strokeWidth: "1.5",
2706
- strokeLinecap: "round",
2707
- strokeLinejoin: "round"
2708
- }
2709
- )
2710
- }
2711
- ),
2712
- "Velocidade"
2713
- ]
2923
+ className: "absolute inset-y-0 left-0 rounded-full bg-white/28",
2924
+ style: { width: `${bufferedPercent}%` }
2714
2925
  }
2715
2926
  ),
2716
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsxs(
2717
- "button",
2927
+ /* @__PURE__ */ jsx(
2928
+ "div",
2718
2929
  {
2719
- type: "button",
2720
- onClick: () => {
2721
- setPlaybackRate(speed);
2722
- closeSettings();
2723
- },
2724
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
2725
- children: [
2726
- /* @__PURE__ */ jsx(
2727
- "svg",
2728
- {
2729
- className: `size-4 shrink-0 ${playbackRate === speed ? "text-white" : "text-transparent"}`,
2730
- viewBox: "0 0 16 16",
2731
- fill: "none",
2732
- children: /* @__PURE__ */ jsx(
2733
- "path",
2734
- {
2735
- d: "M3 8l3.5 3.5L13 4.5",
2736
- stroke: "currentColor",
2737
- strokeWidth: "1.8",
2738
- strokeLinecap: "round",
2739
- strokeLinejoin: "round"
2740
- }
2741
- )
2742
- }
2743
- ),
2744
- /* @__PURE__ */ jsx(
2745
- "span",
2746
- {
2747
- className: playbackRate === speed ? "font-semibold text-white" : "text-white/55",
2748
- children: speed === 1 ? "Normal" : `${speed}\xD7`
2749
- }
2750
- )
2751
- ]
2752
- },
2753
- speed
2754
- )) })
2755
- ] })
2756
- ]
2757
- }
2758
- )
2759
- ] }),
2760
- /* @__PURE__ */ jsxs(
2761
- "div",
2762
- {
2763
- ref: progressRef,
2764
- onPointerMove: handleProgressPointerMove,
2765
- onPointerEnter: handleProgressPointerEnter,
2766
- onPointerLeave: handleProgressPointerLeave,
2767
- onPointerDown: handleProgressPointerDown,
2768
- onPointerUp: handleProgressPointerUp,
2769
- className: "relative mb-2 h-8 cursor-pointer overflow-visible",
2770
- children: [
2771
- /* @__PURE__ */ jsxs(
2930
+ className: "absolute inset-y-0 left-0 rounded-full bg-white",
2931
+ style: { width: `${progressPercent}%`, transition: "width 0.05s linear" }
2932
+ }
2933
+ )
2934
+ ]
2935
+ }
2936
+ ),
2937
+ /* @__PURE__ */ jsx(
2938
+ "div",
2939
+ {
2940
+ ref: progressThumbRef,
2941
+ className: "pointer-events-none absolute rounded-full bg-white shadow-[0_1px_6px_rgba(0,0,0,0.5)]",
2942
+ style: {
2943
+ top: "50%",
2944
+ left: `${progressPercent}%`,
2945
+ transform: "translate(-50%, -50%)",
2946
+ width: "10px",
2947
+ height: "10px"
2948
+ }
2949
+ }
2950
+ ),
2951
+ chapters.length > 0 && duration > 0 && chapters.map((ch, i) => /* @__PURE__ */ jsx(
2952
+ "div",
2953
+ {
2954
+ "data-chapter-marker": true,
2955
+ className: "pointer-events-none absolute top-1/2 -translate-y-1/2 w-0.5 rounded-full bg-white/50",
2956
+ style: { left: `${ch.startTime / duration * 100}%`, height: "3px" }
2957
+ },
2958
+ i
2959
+ )),
2960
+ preview && (() => {
2961
+ const frameW = preview.cue.w ?? 160;
2962
+ const frameH = preview.cue.h ?? 90;
2963
+ const thumbW = 200;
2964
+ const thumbH = Math.round(thumbW * (frameH / frameW));
2965
+ const scale = thumbW / frameW;
2966
+ const isSprite = preview.cue.x != null && preview.cue.y != null;
2967
+ return /* @__PURE__ */ jsxs(
2772
2968
  "div",
2773
2969
  {
2774
- className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/18",
2970
+ className: "pointer-events-none absolute flex flex-col items-center gap-1",
2775
2971
  style: {
2776
- height: isDragging ? "7px" : isHoveringProgress ? "5px" : "3px",
2777
- transition: "height 0.15s ease"
2972
+ bottom: "calc(100% + 6px)",
2973
+ left: preview.left,
2974
+ transform: "translateX(-50%)",
2975
+ zIndex: 80
2778
2976
  },
2779
2977
  children: [
2780
2978
  /* @__PURE__ */ jsx(
2781
2979
  "div",
2782
2980
  {
2783
- className: "absolute inset-y-0 left-0 rounded-full bg-white/28",
2784
- style: { width: `${bufferedPercent}%` }
2981
+ className: "overflow-hidden rounded-lg shadow-2xl ring-1 ring-white/20",
2982
+ style: { width: thumbW, height: thumbH, flexShrink: 0 },
2983
+ children: isSprite ? (
2984
+ // Sprite: need full sheet dimensions to compute backgroundSize correctly.
2985
+ // Load them once from the image's natural size.
2986
+ (() => {
2987
+ const imgUrl = preview.cue.image;
2988
+ if (storyboardSheetUrlRef.current !== imgUrl) {
2989
+ storyboardSheetUrlRef.current = imgUrl;
2990
+ const img = new window.Image();
2991
+ img.onload = () => setStoryboardSheetSize({ w: img.naturalWidth, h: img.naturalHeight });
2992
+ img.src = imgUrl;
2993
+ }
2994
+ if (!storyboardSheetSize) return null;
2995
+ const bsW = storyboardSheetSize.w * scale;
2996
+ const bsH = storyboardSheetSize.h * scale;
2997
+ return /* @__PURE__ */ jsx(
2998
+ "div",
2999
+ {
3000
+ style: {
3001
+ width: thumbW,
3002
+ height: thumbH,
3003
+ backgroundImage: `url(${imgUrl})`,
3004
+ backgroundRepeat: "no-repeat",
3005
+ backgroundPosition: `-${(preview.cue.x ?? 0) * scale}px -${(preview.cue.y ?? 0) * scale}px`,
3006
+ backgroundSize: `${bsW}px ${bsH}px`
3007
+ }
3008
+ }
3009
+ );
3010
+ })()
3011
+ ) : /* @__PURE__ */ jsx(
3012
+ "img",
3013
+ {
3014
+ src: preview.cue.image,
3015
+ alt: "",
3016
+ style: { width: thumbW, height: thumbH, objectFit: "cover", objectPosition: "center", display: "block" }
3017
+ }
3018
+ )
2785
3019
  }
2786
3020
  ),
2787
- /* @__PURE__ */ jsx(
3021
+ /* @__PURE__ */ jsxs(
2788
3022
  "div",
2789
3023
  {
2790
- className: "absolute inset-y-0 left-0 rounded-full bg-white",
2791
- style: { width: `${progressPercent}%`, transition: "width 0.05s linear" }
3024
+ className: "flex items-center gap-1.5 rounded-md px-2 py-0.5 text-[11px] font-semibold text-white/90",
3025
+ style: { background: "rgba(0,0,0,0.55)", backdropFilter: "blur(6px)" },
3026
+ children: [
3027
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatTime(preview.time) }),
3028
+ (() => {
3029
+ const ch = [...chapters].reverse().find((c) => c.startTime <= preview.time);
3030
+ return ch ? /* @__PURE__ */ jsxs(Fragment, { children: [
3031
+ /* @__PURE__ */ jsx("span", { className: "text-white/40", children: "\xB7" }),
3032
+ /* @__PURE__ */ jsx("span", { className: "max-w-36 truncate", children: ch.title })
3033
+ ] }) : null;
3034
+ })()
3035
+ ]
2792
3036
  }
2793
3037
  )
2794
3038
  ]
2795
3039
  }
2796
- ),
2797
- /* @__PURE__ */ jsx(
2798
- "div",
2799
- {
2800
- className: "pointer-events-none absolute rounded-full bg-white shadow-[0_1px_6px_rgba(0,0,0,0.5)]",
2801
- style: {
2802
- top: "50%",
2803
- left: `${progressPercent}%`,
2804
- transform: "translate(-50%, -50%)",
2805
- width: isDragging ? "18px" : isHoveringProgress ? "14px" : "10px",
2806
- height: isDragging ? "18px" : isHoveringProgress ? "14px" : "10px",
2807
- transition: "width 0.2s cubic-bezier(0.34,1.56,0.64,1), height 0.2s cubic-bezier(0.34,1.56,0.64,1)"
2808
- }
2809
- }
2810
- ),
2811
- chapters.length > 0 && duration > 0 && chapters.map((ch, i) => /* @__PURE__ */ jsx(
2812
- "div",
2813
- {
2814
- className: "pointer-events-none absolute top-1/2 -translate-y-1/2 w-0.5 rounded-full bg-white/50",
2815
- style: { left: `${ch.startTime / duration * 100}%`, height: isDragging ? "7px" : isHoveringProgress ? "5px" : "3px", transition: "height 0.15s ease" }
2816
- },
2817
- i
2818
- )),
2819
- preview && (() => {
2820
- const frameW = preview.cue.w ?? 160;
2821
- const frameH = preview.cue.h ?? 90;
2822
- const thumbW = 200;
2823
- const thumbH = Math.round(thumbW * (frameH / frameW));
2824
- const scale = thumbW / frameW;
2825
- const isSprite = preview.cue.x != null && preview.cue.y != null;
3040
+ );
3041
+ })()
3042
+ ]
3043
+ }
3044
+ ),
3045
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
3046
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 @sm:gap-2", children: [
3047
+ /* @__PURE__ */ jsx(
3048
+ "button",
3049
+ {
3050
+ type: "button",
3051
+ onClick: togglePlay,
3052
+ className: "grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10 @sm:size-9",
3053
+ "aria-label": isPlaying ? "Pause" : "Play",
3054
+ children: isPlaying ? /* @__PURE__ */ jsx(Pause, { className: "size-4 @sm:size-5", fill: "white" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-4 @sm:size-5", fill: "white" })
3055
+ }
3056
+ ),
3057
+ /* @__PURE__ */ jsxs("span", { className: "text-[11px] font-medium tabular-nums text-white/80", children: [
3058
+ formatTime(currentTime),
3059
+ /* @__PURE__ */ jsx("span", { className: "text-white/30", children: "/" }),
3060
+ /* @__PURE__ */ jsx("span", { className: "text-white/45", children: formatTime(duration) })
3061
+ ] }),
3062
+ (() => {
3063
+ if (chapters.length === 0) return null;
3064
+ const ch = [...chapters].reverse().find((c) => currentTime >= c.startTime);
3065
+ return ch ? /* @__PURE__ */ jsx("span", { className: "hidden max-w-40 truncate text-[11px] text-white/50 @sm:block", children: ch.title }) : null;
3066
+ })()
3067
+ ] }),
3068
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 @sm:gap-1", children: [
3069
+ parsed.rating && (() => {
3070
+ const REACTIONS = [
3071
+ { key: "LOVE", emoji: "\u2764\uFE0F" },
3072
+ { key: "LIKE", emoji: "\u{1F44D}" },
3073
+ { key: "DISLIKE", emoji: "\u{1F44E}" }
3074
+ ];
3075
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3076
+ REACTIONS.map(({ key, emoji }) => {
3077
+ const count = ratingCounts[key] ?? 0;
3078
+ const active = userReaction === key;
2826
3079
  return /* @__PURE__ */ jsxs(
2827
- "div",
3080
+ "button",
2828
3081
  {
2829
- className: "pointer-events-none absolute flex flex-col items-center gap-1",
2830
- style: {
2831
- bottom: "calc(100% + 6px)",
2832
- left: preview.left,
2833
- transform: "translateX(-50%)",
2834
- zIndex: 80
3082
+ type: "button",
3083
+ onClick: (e) => {
3084
+ e.stopPropagation();
3085
+ const next = active ? null : key;
3086
+ setUserReaction(next);
3087
+ setRatingCounts((prev) => {
3088
+ const updated = { ...prev };
3089
+ const prev_reaction = userReactionRef.current;
3090
+ if (active) updated[key] = Math.max(0, (updated[key] ?? 0) - 1);
3091
+ else {
3092
+ if (prev_reaction) updated[prev_reaction] = Math.max(0, (updated[prev_reaction] ?? 0) - 1);
3093
+ updated[key] = (updated[key] ?? 0) + 1;
3094
+ }
3095
+ return updated;
3096
+ });
3097
+ onReactRef.current?.(next);
2835
3098
  },
3099
+ className: `flex items-center gap-0.5 rounded px-1.5 py-1 text-[11px] transition hover:bg-white/10 ${active ? "opacity-100" : "opacity-50 hover:opacity-80"}`,
3100
+ "aria-label": key.toLowerCase(),
3101
+ "aria-pressed": active,
2836
3102
  children: [
2837
- /* @__PURE__ */ jsx(
2838
- "div",
2839
- {
2840
- className: "overflow-hidden rounded-lg shadow-2xl ring-1 ring-white/20",
2841
- style: { width: thumbW, height: thumbH, flexShrink: 0 },
2842
- children: isSprite ? (
2843
- // Sprite: need full sheet dimensions to compute backgroundSize correctly.
2844
- // Load them once from the image's natural size.
2845
- (() => {
2846
- const imgUrl = preview.cue.image;
2847
- if (storyboardSheetUrlRef.current !== imgUrl) {
2848
- storyboardSheetUrlRef.current = imgUrl;
2849
- const img = new window.Image();
2850
- img.onload = () => setStoryboardSheetSize({ w: img.naturalWidth, h: img.naturalHeight });
2851
- img.src = imgUrl;
2852
- }
2853
- if (!storyboardSheetSize) return null;
2854
- const bsW = storyboardSheetSize.w * scale;
2855
- const bsH = storyboardSheetSize.h * scale;
2856
- return /* @__PURE__ */ jsx(
2857
- "div",
2858
- {
2859
- style: {
2860
- width: thumbW,
2861
- height: thumbH,
2862
- backgroundImage: `url(${imgUrl})`,
2863
- backgroundRepeat: "no-repeat",
2864
- backgroundPosition: `-${(preview.cue.x ?? 0) * scale}px -${(preview.cue.y ?? 0) * scale}px`,
2865
- backgroundSize: `${bsW}px ${bsH}px`
2866
- }
2867
- }
2868
- );
2869
- })()
2870
- ) : /* @__PURE__ */ jsx(
2871
- "img",
2872
- {
2873
- src: preview.cue.image,
2874
- alt: "",
2875
- style: { width: thumbW, height: thumbH, objectFit: "cover", objectPosition: "center", display: "block" }
2876
- }
2877
- )
2878
- }
2879
- ),
2880
- /* @__PURE__ */ jsx(
2881
- "span",
2882
- {
2883
- className: "rounded-md px-2 py-0.5 text-[11px] font-semibold tabular-nums text-white/90",
2884
- style: { background: "rgba(0,0,0,0.55)", backdropFilter: "blur(6px)" },
2885
- children: formatTime(preview.time)
2886
- }
2887
- )
3103
+ /* @__PURE__ */ jsx("span", { children: emoji }),
3104
+ count > 0 && /* @__PURE__ */ jsx("span", { className: "text-white/70 tabular-nums", children: count })
2888
3105
  ]
2889
- }
3106
+ },
3107
+ key
2890
3108
  );
2891
- })()
2892
- ]
2893
- }
2894
- ),
2895
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
2896
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 @sm:gap-2", children: [
2897
- /* @__PURE__ */ jsx(
2898
- "button",
2899
- {
2900
- type: "button",
2901
- onClick: togglePlay,
2902
- className: "grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10 @sm:size-9",
2903
- "aria-label": isPlaying ? "Pause" : "Play",
2904
- children: isPlaying ? /* @__PURE__ */ jsx(Pause, { className: "size-4 @sm:size-5", fill: "white" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-4 @sm:size-5", fill: "white" })
2905
- }
2906
- ),
2907
- /* @__PURE__ */ jsxs("span", { className: "text-[11px] font-medium tabular-nums text-white/80", children: [
2908
- formatTime(currentTime),
2909
- /* @__PURE__ */ jsx("span", { className: "text-white/30", children: "/" }),
2910
- /* @__PURE__ */ jsx("span", { className: "text-white/45", children: formatTime(duration) })
2911
- ] }),
2912
- (() => {
2913
- if (chapters.length === 0) return null;
2914
- const ch = [...chapters].reverse().find((c) => currentTime >= c.startTime);
2915
- return ch ? /* @__PURE__ */ jsx("span", { className: "hidden max-w-40 truncate text-[11px] text-white/50 @sm:block", children: ch.title }) : null;
2916
- })()
2917
- ] }),
2918
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 @sm:gap-1", children: [
2919
- parsed.rating && (() => {
2920
- const REACTIONS = [
2921
- { key: "LOVE", emoji: "\u2764\uFE0F" },
2922
- { key: "LIKE", emoji: "\u{1F44D}" },
2923
- { key: "DISLIKE", emoji: "\u{1F44E}" }
2924
- ];
2925
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2926
- REACTIONS.map(({ key, emoji }) => {
2927
- const count = ratingCounts[key] ?? 0;
2928
- const active = userReaction === key;
2929
- return /* @__PURE__ */ jsxs(
2930
- "button",
2931
- {
2932
- type: "button",
2933
- onClick: (e) => {
2934
- e.stopPropagation();
2935
- const next = active ? null : key;
2936
- setUserReaction(next);
2937
- setRatingCounts((prev) => {
2938
- const updated = { ...prev };
2939
- const prev_reaction = userReactionRef.current;
2940
- if (active) updated[key] = Math.max(0, (updated[key] ?? 0) - 1);
2941
- else {
2942
- if (prev_reaction) updated[prev_reaction] = Math.max(0, (updated[prev_reaction] ?? 0) - 1);
2943
- updated[key] = (updated[key] ?? 0) + 1;
2944
- }
2945
- return updated;
2946
- });
2947
- onReactRef.current?.(next);
2948
- },
2949
- className: `flex items-center gap-0.5 rounded px-1.5 py-1 text-[11px] transition hover:bg-white/10 ${active ? "opacity-100" : "opacity-50 hover:opacity-80"}`,
2950
- "aria-label": key.toLowerCase(),
2951
- "aria-pressed": active,
2952
- children: [
2953
- /* @__PURE__ */ jsx("span", { children: emoji }),
2954
- count > 0 && /* @__PURE__ */ jsx("span", { className: "text-white/70 tabular-nums", children: count })
2955
- ]
2956
- },
2957
- key
2958
- );
2959
- }),
2960
- /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" })
2961
- ] });
2962
- })(),
2963
- /* @__PURE__ */ jsx(
2964
- VolumeSlider,
2965
- {
2966
- volume: isMuted ? 0 : volume,
2967
- onMuteToggle: () => setIsMuted((v) => !v),
2968
- onVolumeChange: (v) => {
2969
- setVolume(v);
2970
- setIsMuted(v === 0);
2971
- },
2972
- isMuted
2973
- }
2974
- ),
2975
- /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
2976
- captions.length > 0 && /* @__PURE__ */ jsx(
2977
- "button",
2978
- {
2979
- type: "button",
2980
- onClick: () => {
2981
- const next = subtitleMode === "off" ? captions[0]?.srclang ?? "off" : "off";
2982
- setSubtitleMode(next);
2983
- setSubtitleStyle((st) => ({ ...st, track: next }));
2984
- },
2985
- className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
2986
- "aria-label": "Captions",
2987
- children: /* @__PURE__ */ jsx(Captions$1, { className: "size-4 @sm:size-5" })
2988
- }
2989
- ),
2990
- /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
2991
- "button",
2992
- {
2993
- type: "button",
2994
- onClick: () => settingsOpen ? closeSettings() : openSettings(),
2995
- className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${settingsOpen ? "text-white" : "text-white/60"}`,
2996
- "aria-label": "Settings",
2997
- children: /* @__PURE__ */ jsx(Settings, { className: "size-4 @sm:size-5" })
2998
- }
2999
- ) }),
3000
- /* @__PURE__ */ jsx(
3001
- "button",
3002
- {
3003
- type: "button",
3004
- onClick: toggleFullscreen,
3005
- className: "grid size-8 place-items-center text-white/60 transition hover:scale-110 hover:text-white/80 @sm:size-10",
3006
- "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
3007
- children: isFullscreen ? /* @__PURE__ */ jsx(Minimize, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Maximize, { className: "size-4 @sm:size-5" })
3008
- }
3009
- )
3010
- ] })
3109
+ }),
3110
+ /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" })
3111
+ ] });
3112
+ })(),
3113
+ /* @__PURE__ */ jsx(
3114
+ VolumeSlider,
3115
+ {
3116
+ volume: isMuted ? 0 : volume,
3117
+ onMuteToggle: () => setIsMuted((v) => !v),
3118
+ onVolumeChange: (v) => {
3119
+ setVolume(v);
3120
+ setIsMuted(v === 0);
3121
+ },
3122
+ isMuted
3123
+ }
3124
+ ),
3125
+ /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
3126
+ captions.length > 0 && /* @__PURE__ */ jsx(
3127
+ "button",
3128
+ {
3129
+ type: "button",
3130
+ onClick: () => {
3131
+ const next = subtitleMode === "off" ? captions[0]?.srclang ?? "off" : "off";
3132
+ setSubtitleMode(next);
3133
+ setSubtitleStyle((st) => ({ ...st, track: next }));
3134
+ },
3135
+ className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
3136
+ "aria-label": "Captions",
3137
+ children: /* @__PURE__ */ jsx(Captions$1, { className: "size-4 @sm:size-5" })
3138
+ }
3139
+ ),
3140
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
3141
+ "button",
3142
+ {
3143
+ type: "button",
3144
+ onClick: () => settingsOpen ? closeSettings() : openSettings(),
3145
+ className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${settingsOpen ? "text-white" : "text-white/60"}`,
3146
+ "aria-label": "Settings",
3147
+ children: /* @__PURE__ */ jsx(Settings, { className: "size-4 @sm:size-5" })
3148
+ }
3149
+ ) }),
3150
+ /* @__PURE__ */ jsx(
3151
+ "button",
3152
+ {
3153
+ type: "button",
3154
+ onClick: toggleFullscreen,
3155
+ className: "grid size-8 place-items-center text-white/60 transition hover:scale-110 hover:text-white/80 @sm:size-10",
3156
+ "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
3157
+ children: isFullscreen ? /* @__PURE__ */ jsx(Minimize, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Maximize, { className: "size-4 @sm:size-5" })
3158
+ }
3159
+ )
3011
3160
  ] })
3012
- ]
3013
- }
3014
- )
3015
- ]
3016
- }
3017
- ),
3018
- activeCue && /* @__PURE__ */ jsx(
3019
- "div",
3020
- {
3021
- className: `pointer-events-none absolute inset-x-0 z-40 flex justify-center px-4 transition-all duration-200${controlsVisible ? "bottom-20 @sm:bottom-24 @lg:bottom-28" : "bottom-4 @sm:bottom-6"}`,
3022
- children: /* @__PURE__ */ jsx(
3023
- "div",
3024
- {
3025
- className: "max-w-[80%] rounded-lg px-4 py-1.5 text-center font-medium leading-snug",
3026
- style: {
3027
- fontSize: (() => {
3028
- const base = Math.max(12, Math.min(playerHeight * 0.028, 32));
3029
- if (subtitleStyle.size === "small") return `${base * 0.75}px`;
3030
- if (subtitleStyle.size === "large") return `${base * 1.35}px`;
3031
- if (subtitleStyle.size === "xlarge") return `${base * 1.8}px`;
3032
- return `${base}px`;
3033
- })(),
3034
- color: subtitleStyle.color === "yellow" ? "#facc15" : subtitleStyle.color === "cyan" ? "#22d3ee" : "#ffffff",
3035
- backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.55)",
3036
- backdropFilter: subtitleStyle.bg === "semi" ? "blur(6px)" : void 0,
3037
- textShadow: subtitleStyle.bg === "none" ? "0 1px 8px rgba(0,0,0,1), 0 0 16px rgba(0,0,0,0.9)" : "0 1px 3px rgba(0,0,0,0.5)"
3038
- },
3039
- children: activeCue
3161
+ ] })
3162
+ ]
3040
3163
  }
3041
3164
  )
3042
- }
3043
- )
3044
- ]
3045
- }
3046
- )
3047
- ]
3165
+ ]
3166
+ }
3167
+ ),
3168
+ activeCue && /* @__PURE__ */ jsx(
3169
+ "div",
3170
+ {
3171
+ className: `pointer-events-none absolute inset-x-0 z-40 flex justify-center px-4 transition-all duration-200${controlsVisible ? "bottom-20 @sm:bottom-24 @lg:bottom-28" : "bottom-4 @sm:bottom-6"}`,
3172
+ children: /* @__PURE__ */ jsx(
3173
+ "div",
3174
+ {
3175
+ className: "max-w-[80%] rounded-lg px-4 py-1.5 text-center font-medium leading-snug",
3176
+ style: {
3177
+ fontSize: (() => {
3178
+ const base = Math.max(12, Math.min(playerHeight * 0.028, 32));
3179
+ if (subtitleStyle.size === "small") return `${base * 0.75}px`;
3180
+ if (subtitleStyle.size === "large") return `${base * 1.35}px`;
3181
+ if (subtitleStyle.size === "xlarge") return `${base * 1.8}px`;
3182
+ return `${base}px`;
3183
+ })(),
3184
+ color: subtitleStyle.color === "yellow" ? "#facc15" : subtitleStyle.color === "cyan" ? "#22d3ee" : "#ffffff",
3185
+ backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.55)",
3186
+ backdropFilter: subtitleStyle.bg === "semi" ? "blur(6px)" : void 0,
3187
+ textShadow: subtitleStyle.bg === "none" ? "0 1px 8px rgba(0,0,0,1), 0 0 16px rgba(0,0,0,0.9)" : "0 1px 3px rgba(0,0,0,0.5)"
3188
+ },
3189
+ children: activeCue
3190
+ }
3191
+ )
3192
+ }
3193
+ )
3194
+ ]
3195
+ }
3196
+ )
3048
3197
  }
3049
3198
  );
3050
3199
  }
@@ -3058,6 +3207,9 @@ function VolumeSlider({
3058
3207
  const [hovered, setHovered] = useState(false);
3059
3208
  const [dragging, setDragging] = useState(false);
3060
3209
  const trackRef = useRef(null);
3210
+ const sliderWrapRef = useRef(null);
3211
+ const railRef = useRef(null);
3212
+ const thumbRef = useRef(null);
3061
3213
  const expanded = hovered || dragging;
3062
3214
  const seek = useCallback((clientX) => {
3063
3215
  const track = trackRef.current;
@@ -3075,6 +3227,31 @@ function VolumeSlider({
3075
3227
  if (dragging) seek(e.clientX);
3076
3228
  }, [dragging, seek]);
3077
3229
  const onPointerUp = useCallback(() => setDragging(false), []);
3230
+ useEffect(() => {
3231
+ const wrap = sliderWrapRef.current;
3232
+ if (!wrap) return;
3233
+ gsap.killTweensOf(wrap);
3234
+ gsap.to(wrap, {
3235
+ width: expanded ? 64 : 0,
3236
+ opacity: expanded ? 1 : 0,
3237
+ duration: 0.2,
3238
+ ease: "power2.inOut"
3239
+ });
3240
+ }, [expanded]);
3241
+ useEffect(() => {
3242
+ const rail = railRef.current;
3243
+ const thumb = thumbRef.current;
3244
+ const targetRailH = dragging ? 5 : hovered ? 4 : 3;
3245
+ const targetThumbSize = dragging ? 14 : hovered ? 11 : 0;
3246
+ if (rail) {
3247
+ gsap.killTweensOf(rail);
3248
+ gsap.to(rail, { height: targetRailH, duration: 0.15, ease: "power1.inOut" });
3249
+ }
3250
+ if (thumb) {
3251
+ gsap.killTweensOf(thumb);
3252
+ gsap.to(thumb, { width: targetThumbSize, height: targetThumbSize, duration: 0.15, ease: "power1.inOut" });
3253
+ }
3254
+ }, [dragging, hovered]);
3078
3255
  const fillPercent = volume * 100;
3079
3256
  return /* @__PURE__ */ jsxs(
3080
3257
  "div",
@@ -3098,10 +3275,10 @@ function VolumeSlider({
3098
3275
  /* @__PURE__ */ jsx(
3099
3276
  "div",
3100
3277
  {
3278
+ ref: sliderWrapRef,
3101
3279
  style: {
3102
- width: expanded ? "64px" : "0px",
3103
- opacity: expanded ? 1 : 0,
3104
- transition: "width 0.2s ease, opacity 0.2s ease",
3280
+ width: "0px",
3281
+ opacity: 0,
3105
3282
  overflow: "hidden"
3106
3283
  },
3107
3284
  children: /* @__PURE__ */ jsxs(
@@ -3117,11 +3294,9 @@ function VolumeSlider({
3117
3294
  /* @__PURE__ */ jsx(
3118
3295
  "div",
3119
3296
  {
3297
+ ref: railRef,
3120
3298
  className: "absolute inset-x-0 rounded-full bg-white/20",
3121
- style: {
3122
- height: dragging ? "5px" : hovered ? "4px" : "3px",
3123
- transition: "height 0.15s ease"
3124
- },
3299
+ style: { height: "3px" },
3125
3300
  children: /* @__PURE__ */ jsx(
3126
3301
  "div",
3127
3302
  {
@@ -3134,12 +3309,12 @@ function VolumeSlider({
3134
3309
  /* @__PURE__ */ jsx(
3135
3310
  "div",
3136
3311
  {
3312
+ ref: thumbRef,
3137
3313
  className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white shadow-md",
3138
3314
  style: {
3139
3315
  left: `${fillPercent}%`,
3140
- width: dragging ? "14px" : hovered ? "11px" : "0px",
3141
- height: dragging ? "14px" : hovered ? "11px" : "0px",
3142
- transition: "width 0.15s ease, height 0.15s ease"
3316
+ width: "0px",
3317
+ height: "0px"
3143
3318
  }
3144
3319
  }
3145
3320
  )