@geekapps/silo-elements-nextjs 0.2.70 → 0.3.1

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.
@@ -118,6 +118,7 @@ function Video({
118
118
  const containerRef = useRef(null);
119
119
  const chromeRef = useRef(null);
120
120
  const playerRef = useRef(null);
121
+ const showAgeRatingRef = useRef(null);
121
122
  const videoRef = useRef(null);
122
123
  const progressRef = useRef(null);
123
124
  const hlsRef = useRef(null);
@@ -130,7 +131,6 @@ function Video({
130
131
  const [selectedAudio, setSelectedAudio] = useState(0);
131
132
  const [settingsOpen, setSettingsOpen] = useState(false);
132
133
  const [settingsVisible, setSettingsVisible] = useState(false);
133
- const settingsCloseTimerRef = useRef(null);
134
134
  const [settingsTab, setSettingsTab] = useState("root");
135
135
  const [playbackRate, setPlaybackRate] = useState(1);
136
136
  const [subtitleStyle, setSubtitleStyle] = useState({
@@ -178,13 +178,20 @@ function Video({
178
178
  const dragPointerIdRef = useRef(null);
179
179
  const [isPlaying, setIsPlaying] = useState(false);
180
180
  const [hasPlayed, setHasPlayed] = useState(false);
181
- const [ageRatingOverlay, setAgeRatingOverlay] = useState(false);
182
- const ageRatingTimerRef = useRef(null);
181
+ const ageRatingTlRef = useRef(null);
183
182
  const ageRatingPauseTimerRef = useRef(null);
183
+ const ageRatingWrapRef = useRef(null);
184
+ const ageRatingIconRef = useRef(null);
185
+ const ageRatingTextRef = useRef(null);
184
186
  const [clickIcon, setClickIcon] = useState(null);
185
187
  const clickIconTimerRef = useRef(null);
188
+ const clickIconRef = useRef(null);
186
189
  const [isLoading, setIsLoading] = useState(true);
187
190
  const [controlsVisible, setControlsVisible] = useState(true);
191
+ const settingsPanelRef = useRef(null);
192
+ const settingsContentRef = useRef(null);
193
+ const progressTrackRef = useRef(null);
194
+ const progressThumbRef = useRef(null);
188
195
  const [volume, setVolume] = useState(defaultVolume);
189
196
  const [isMuted, setIsMuted] = useState(false);
190
197
  const [isFullscreen, setIsFullscreen] = useState(false);
@@ -250,6 +257,9 @@ function Video({
250
257
  setControlsVisible(false);
251
258
  }, 2400);
252
259
  }
260
+ if (video?.paused) {
261
+ showAgeRatingRef.current?.();
262
+ }
253
263
  }, [autoHideControls]);
254
264
  useEffect(() => {
255
265
  if (!containerRef.current) return;
@@ -274,13 +284,96 @@ function Video({
274
284
  const openSettings = useCallback(() => {
275
285
  setSettingsOpen(true);
276
286
  setSettingsTab("root");
277
- window.setTimeout(() => setSettingsVisible(true), 10);
287
+ setSettingsVisible(true);
278
288
  }, []);
279
289
  const closeSettings = useCallback(() => {
280
- setSettingsVisible(false);
281
- if (settingsCloseTimerRef.current) window.clearTimeout(settingsCloseTimerRef.current);
282
- settingsCloseTimerRef.current = window.setTimeout(() => setSettingsOpen(false), 200);
290
+ const panel = settingsPanelRef.current;
291
+ if (panel) {
292
+ gsap.killTweensOf(panel);
293
+ gsap.to(panel, {
294
+ opacity: 0,
295
+ y: 8,
296
+ scale: 0.97,
297
+ duration: 0.18,
298
+ ease: "power2.in",
299
+ onComplete: () => {
300
+ setSettingsOpen(false);
301
+ setSettingsVisible(false);
302
+ }
303
+ });
304
+ } else {
305
+ setSettingsOpen(false);
306
+ setSettingsVisible(false);
307
+ }
283
308
  }, []);
309
+ useEffect(() => {
310
+ if (!settingsOpen) return;
311
+ const panel = settingsPanelRef.current;
312
+ if (!panel) return;
313
+ gsap.killTweensOf(panel);
314
+ gsap.fromTo(
315
+ panel,
316
+ { opacity: 0, y: 8, scale: 0.97 },
317
+ { opacity: 1, y: 0, scale: 1, duration: 0.2, ease: "power2.out" }
318
+ );
319
+ }, [settingsOpen]);
320
+ useEffect(() => {
321
+ const el = settingsContentRef.current;
322
+ if (!el) return;
323
+ gsap.killTweensOf(el);
324
+ gsap.fromTo(
325
+ el,
326
+ { opacity: 0, x: 12 },
327
+ { opacity: 1, x: 0, duration: 0.18, ease: "power2.out" }
328
+ );
329
+ }, [settingsTab]);
330
+ useEffect(() => {
331
+ const el = chromeRef.current;
332
+ const player = playerRef.current;
333
+ if (!el) return;
334
+ gsap.killTweensOf(el);
335
+ gsap.to(el, {
336
+ opacity: controlsVisible ? 1 : 0,
337
+ duration: 0.2,
338
+ ease: "power1.inOut"
339
+ });
340
+ el.style.pointerEvents = controlsVisible ? "" : "none";
341
+ if (player) {
342
+ player.style.cursor = controlsVisible ? "" : "none";
343
+ }
344
+ }, [controlsVisible]);
345
+ useEffect(() => {
346
+ const el = clickIconRef.current;
347
+ if (!el) return;
348
+ gsap.killTweensOf(el);
349
+ if (clickIcon) {
350
+ gsap.to(el, { opacity: 1, duration: 0.08, ease: "power1.in" });
351
+ } else {
352
+ gsap.to(el, { opacity: 0, duration: 0.45, ease: "power1.out" });
353
+ }
354
+ }, [clickIcon]);
355
+ useEffect(() => {
356
+ const track = progressTrackRef.current;
357
+ const thumb = progressThumbRef.current;
358
+ const container = progressRef.current;
359
+ const targetH = isDragging ? 7 : isHoveringProgress ? 5 : 3;
360
+ const targetW = isDragging ? 18 : isHoveringProgress ? 14 : 10;
361
+ if (track) {
362
+ gsap.killTweensOf(track);
363
+ gsap.to(track, { height: targetH, duration: 0.15, ease: "power1.inOut" });
364
+ }
365
+ if (thumb) {
366
+ gsap.killTweensOf(thumb);
367
+ gsap.to(thumb, { width: targetW, height: targetW, duration: 0.2, ease: "back.out(1.7)" });
368
+ }
369
+ if (container) {
370
+ const markers = container.querySelectorAll("[data-chapter-marker]");
371
+ markers.forEach((el) => {
372
+ gsap.killTweensOf(el);
373
+ gsap.to(el, { height: targetH, duration: 0.15, ease: "power1.inOut" });
374
+ });
375
+ }
376
+ }, [isDragging, isHoveringProgress]);
284
377
  useEffect(() => {
285
378
  if (sourceIndex >= parsed.sources.length) {
286
379
  setSourceIndex(initialSourceIndex);
@@ -304,14 +397,43 @@ function Video({
304
397
  setDuration(Number.isFinite(video.duration) ? video.duration : 0);
305
398
  applySubtitleMode(subtitleMode);
306
399
  };
400
+ const hideAgeRating = () => {
401
+ const wrap = ageRatingWrapRef.current;
402
+ if (!wrap) return;
403
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
404
+ gsap.to(wrap, { opacity: 0, duration: 0.4, ease: "power2.inOut" });
405
+ };
307
406
  const showAgeRating = () => {
308
407
  if (!parsed.ageRating?.data) return;
309
- if (ageRatingTimerRef.current) window.clearTimeout(ageRatingTimerRef.current);
310
- ageRatingTimerRef.current = window.setTimeout(() => {
311
- setAgeRatingOverlay(true);
312
- ageRatingTimerRef.current = window.setTimeout(() => setAgeRatingOverlay(false), 8e3);
313
- }, 600);
408
+ const wrap = ageRatingWrapRef.current;
409
+ const icon = ageRatingIconRef.current;
410
+ const text = ageRatingTextRef.current;
411
+ if (!wrap) return;
412
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
413
+ const HOLD = 12;
414
+ const tl = gsap.timeline({ delay: 0.6 });
415
+ tl.fromTo(wrap, { opacity: 0 }, { opacity: 1, duration: 0.5, ease: "power2.out" });
416
+ if (icon) {
417
+ tl.fromTo(
418
+ icon,
419
+ { opacity: 0, scale: 0.7 },
420
+ { opacity: 1, scale: 1, duration: 0.55, ease: "back.out(1.6)" },
421
+ "-=0.2"
422
+ );
423
+ }
424
+ if (text) {
425
+ tl.fromTo(
426
+ text,
427
+ { opacity: 0, x: -10 },
428
+ { opacity: 1, x: 0, duration: 0.4, ease: "power2.out" },
429
+ "-=0.25"
430
+ );
431
+ }
432
+ tl.to({}, { duration: HOLD });
433
+ tl.to(wrap, { opacity: 0, duration: 0.7, ease: "power2.inOut" });
434
+ ageRatingTlRef.current = tl;
314
435
  };
436
+ showAgeRatingRef.current = showAgeRating;
315
437
  const onPlay = () => {
316
438
  setIsPlaying(true);
317
439
  if (ageRatingPauseTimerRef.current) {
@@ -327,12 +449,13 @@ function Video({
327
449
  const onPause = () => {
328
450
  setIsPlaying(false);
329
451
  setControlsVisible(true);
452
+ hideAgeRating();
330
453
  if (parsed.ageRating?.data) {
331
454
  if (ageRatingPauseTimerRef.current) window.clearTimeout(ageRatingPauseTimerRef.current);
332
455
  ageRatingPauseTimerRef.current = window.setTimeout(() => {
333
456
  showAgeRating();
334
457
  ageRatingPauseTimerRef.current = null;
335
- }, 5 * 60 * 1e3);
458
+ }, 60 * 1e3);
336
459
  }
337
460
  };
338
461
  const onWaiting = () => setIsLoading(true);
@@ -357,7 +480,7 @@ function Video({
357
480
  video.removeEventListener("waiting", onWaiting);
358
481
  video.removeEventListener("canplay", onCanPlay);
359
482
  video.removeEventListener("ended", onEnded);
360
- if (ageRatingTimerRef.current) window.clearTimeout(ageRatingTimerRef.current);
483
+ if (ageRatingTlRef.current) ageRatingTlRef.current.kill();
361
484
  if (ageRatingPauseTimerRef.current) window.clearTimeout(ageRatingPauseTimerRef.current);
362
485
  };
363
486
  }, [applySubtitleMode, subtitleMode, showControlsTemporarily]);
@@ -1010,949 +1133,940 @@ function Video({
1010
1133
  "."
1011
1134
  ] });
1012
1135
  }
1013
- return /* @__PURE__ */ jsxs(
1136
+ return /* @__PURE__ */ jsx(
1014
1137
  "div",
1015
1138
  {
1016
1139
  ref: containerRef,
1017
1140
  className: `@container mx-auto w-full max-w-6xl${className ?? ""}`,
1018
- children: [
1019
- /* @__PURE__ */ jsx("style", { children: `
1020
- @keyframes silo-ar-bg{0%{opacity:0}10%{opacity:1}80%{opacity:1}100%{opacity:0}}
1021
- @keyframes silo-ar-icon{0%,8%{opacity:0;transform:scale(0.82)}18%{opacity:1;transform:scale(1)}80%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(1)}}
1022
- @keyframes silo-ar-text{0%,18%{opacity:0;transform:translateX(-6px)}30%{opacity:1;transform:translateX(0)}80%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(0)}}
1023
- ` }),
1024
- /* @__PURE__ */ jsxs(
1025
- "div",
1026
- {
1027
- ref: playerRef,
1028
- tabIndex: 0,
1029
- onKeyDown: handleKeyDown,
1030
- onMouseMove: showControlsTemporarily,
1031
- onMouseLeave: () => {
1141
+ children: /* @__PURE__ */ jsxs(
1142
+ "div",
1143
+ {
1144
+ ref: playerRef,
1145
+ tabIndex: 0,
1146
+ onKeyDown: handleKeyDown,
1147
+ onMouseMove: showControlsTemporarily,
1148
+ onMouseLeave: () => {
1149
+ closeSettings();
1150
+ if (isPlaying && autoHideControls) {
1151
+ setControlsVisible(false);
1152
+ }
1153
+ },
1154
+ onBlur: (e) => {
1155
+ if (!e.currentTarget.contains(e.relatedTarget)) {
1032
1156
  closeSettings();
1033
- if (isPlaying && autoHideControls) {
1034
- setControlsVisible(false);
1157
+ }
1158
+ },
1159
+ onTouchStart: showControlsTemporarily,
1160
+ onTouchMove: showControlsTemporarily,
1161
+ 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",
1162
+ style: fixedHeight ? {
1163
+ height: typeof fixedHeight === "number" ? `${fixedHeight}px` : fixedHeight
1164
+ } : maxHeight ? {
1165
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
1166
+ aspectRatio: "16/9"
1167
+ } : { aspectRatio: "16/9" },
1168
+ children: [
1169
+ /* @__PURE__ */ jsxs(
1170
+ "video",
1171
+ {
1172
+ ref: videoRef,
1173
+ className: `h-full w-full ${isFullscreen ? "object-contain" : "object-cover"}`,
1174
+ playsInline: true,
1175
+ preload: "metadata",
1176
+ crossOrigin: "anonymous",
1177
+ children: [
1178
+ captions.map((subtitle) => /* @__PURE__ */ jsx(
1179
+ "track",
1180
+ {
1181
+ kind: "subtitles",
1182
+ src: subtitle.src,
1183
+ srcLang: subtitle.srclang,
1184
+ label: subtitle.label,
1185
+ default: subtitle.default
1186
+ },
1187
+ `${activeSource.src}-${subtitle.srclang}-${subtitle.src}`
1188
+ )),
1189
+ parsed.storyboard?.src && /* @__PURE__ */ jsx(
1190
+ "track",
1191
+ {
1192
+ kind: "metadata",
1193
+ label: "thumbnails",
1194
+ src: parsed.storyboard.src
1195
+ }
1196
+ )
1197
+ ]
1035
1198
  }
1036
- },
1037
- onBlur: (e) => {
1038
- if (!e.currentTarget.contains(e.relatedTarget)) {
1039
- closeSettings();
1199
+ ),
1200
+ poster && !hasPlayed && /* @__PURE__ */ jsx(
1201
+ "img",
1202
+ {
1203
+ src: poster,
1204
+ "aria-hidden": true,
1205
+ className: "pointer-events-none absolute inset-0 h-full w-full object-contain bg-black"
1040
1206
  }
1041
- },
1042
- onTouchStart: showControlsTemporarily,
1043
- onTouchMove: showControlsTemporarily,
1044
- 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",
1045
- style: fixedHeight ? {
1046
- height: typeof fixedHeight === "number" ? `${fixedHeight}px` : fixedHeight
1047
- } : maxHeight ? {
1048
- maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
1049
- aspectRatio: "16/9"
1050
- } : { aspectRatio: "16/9" },
1051
- children: [
1052
- /* @__PURE__ */ jsxs(
1053
- "video",
1054
- {
1055
- ref: videoRef,
1056
- className: `h-full w-full ${isFullscreen ? "object-contain" : "object-cover"}`,
1057
- playsInline: true,
1058
- preload: "metadata",
1059
- crossOrigin: "anonymous",
1060
- children: [
1061
- captions.map((subtitle) => /* @__PURE__ */ jsx(
1062
- "track",
1063
- {
1064
- kind: "subtitles",
1065
- src: subtitle.src,
1066
- srcLang: subtitle.srclang,
1067
- label: subtitle.label,
1068
- default: subtitle.default
1069
- },
1070
- `${activeSource.src}-${subtitle.srclang}-${subtitle.src}`
1071
- )),
1072
- parsed.storyboard?.src && /* @__PURE__ */ jsx(
1073
- "track",
1074
- {
1075
- kind: "metadata",
1076
- label: "thumbnails",
1077
- src: parsed.storyboard.src
1078
- }
1079
- )
1080
- ]
1081
- }
1082
- ),
1083
- poster && !hasPlayed && /* @__PURE__ */ jsx(
1084
- "img",
1085
- {
1086
- src: poster,
1087
- "aria-hidden": true,
1088
- className: "pointer-events-none absolute inset-0 h-full w-full object-contain bg-black"
1089
- }
1090
- ),
1091
- ageRatingOverlay && parsed.ageRating?.data && (() => {
1092
- const ar = parsed.ageRating;
1093
- const regionKey = resolveAgeRatingRegion(ar.locale, ar.data);
1094
- if (!regionKey) return null;
1095
- const code = ar.data[regionKey];
1096
- const lookupKey = `${regionKey}:${code}`;
1097
- const info = ar.lookup?.[lookupKey];
1098
- const dur = "8s";
1099
- return /* @__PURE__ */ jsx(
1100
- "div",
1101
- {
1102
- className: "pointer-events-none absolute inset-0 z-40 flex items-end justify-start",
1103
- style: {
1104
- background: "linear-gradient(to right, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.45) 38%, transparent 62%)",
1105
- animation: `silo-ar-bg ${dur} forwards`
1106
- },
1107
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3.5 px-6 py-6 @sm:px-8 @sm:py-8", children: [
1108
- /* @__PURE__ */ jsx("div", { style: { animation: `silo-ar-icon ${dur} forwards` }, 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 }) }),
1109
- (info?.title || info?.description) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", style: { animation: `silo-ar-text ${dur} forwards` }, children: [
1110
- 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 }),
1111
- 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 })
1112
- ] })
1113
- ] })
1114
- }
1115
- );
1116
- })(),
1117
- /* @__PURE__ */ jsx(
1207
+ ),
1208
+ parsed.ageRating?.data && (() => {
1209
+ const ar = parsed.ageRating;
1210
+ const regionKey = resolveAgeRatingRegion(ar.locale, ar.data);
1211
+ if (!regionKey) return null;
1212
+ const code = ar.data[regionKey];
1213
+ const lookupKey = `${regionKey}:${code}`;
1214
+ const info = ar.lookup?.[lookupKey];
1215
+ return /* @__PURE__ */ jsx(
1118
1216
  "div",
1119
1217
  {
1120
- className: "pointer-events-none absolute inset-0 z-10 grid place-items-center",
1218
+ ref: ageRatingWrapRef,
1219
+ className: "pointer-events-none absolute inset-0 z-20 flex items-start justify-start",
1121
1220
  style: {
1122
- opacity: clickIcon ? 1 : 0,
1123
- transition: clickIcon ? "opacity 0.08s ease-in" : "opacity 0.45s ease-out"
1221
+ opacity: 0,
1222
+ background: "linear-gradient(135deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.4) 40%, transparent 65%)"
1124
1223
  },
1125
- 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(
1126
- Play,
1224
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3.5 px-5 pt-5 @sm:px-7 @sm:pt-7", children: [
1225
+ /* @__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 }) }),
1226
+ (info?.title || info?.description) && /* @__PURE__ */ jsxs("div", { ref: ageRatingTextRef, className: "flex flex-col gap-0.5", style: { opacity: 0 }, children: [
1227
+ 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 }),
1228
+ 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 })
1229
+ ] })
1230
+ ] })
1231
+ }
1232
+ );
1233
+ })(),
1234
+ /* @__PURE__ */ jsx(
1235
+ "div",
1236
+ {
1237
+ ref: clickIconRef,
1238
+ className: "pointer-events-none absolute inset-0 z-10 grid place-items-center",
1239
+ style: { opacity: 0 },
1240
+ 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(
1241
+ Play,
1242
+ {
1243
+ className: "ml-0.5 size-7 @sm:size-9 @lg:size-11",
1244
+ fill: "white"
1245
+ }
1246
+ ) })
1247
+ }
1248
+ ),
1249
+ 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" }) }),
1250
+ /* @__PURE__ */ jsxs(
1251
+ "div",
1252
+ {
1253
+ ref: chromeRef,
1254
+ onClick: togglePlay,
1255
+ className: `absolute inset-0 z-30 flex flex-col ${isFullscreen ? "justify-between" : "justify-end"}`,
1256
+ children: [
1257
+ 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" }),
1258
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
1259
+ isFullscreen && /* @__PURE__ */ jsx(
1260
+ "header",
1127
1261
  {
1128
- className: "ml-0.5 size-7 @sm:size-9 @lg:size-11",
1129
- fill: "white"
1262
+ onClick: (e) => e.stopPropagation(),
1263
+ 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",
1264
+ children: /* @__PURE__ */ jsxs("div", { children: [
1265
+ title && /* @__PURE__ */ jsx(
1266
+ "h1",
1267
+ {
1268
+ className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl",
1269
+ style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" },
1270
+ children: title
1271
+ }
1272
+ ),
1273
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
1274
+ ] })
1130
1275
  }
1131
- ) })
1132
- }
1133
- ),
1134
- 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" }) }),
1135
- /* @__PURE__ */ jsxs(
1136
- "div",
1137
- {
1138
- ref: chromeRef,
1139
- onClick: togglePlay,
1140
- 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"}`,
1141
- children: [
1142
- 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" }),
1143
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
1144
- isFullscreen && /* @__PURE__ */ jsx(
1145
- "header",
1146
- {
1147
- onClick: (e) => e.stopPropagation(),
1148
- 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",
1149
- children: /* @__PURE__ */ jsxs("div", { children: [
1150
- title && /* @__PURE__ */ jsx(
1151
- "h1",
1276
+ ),
1277
+ /* @__PURE__ */ jsxs(
1278
+ "footer",
1279
+ {
1280
+ onClick: (e) => e.stopPropagation(),
1281
+ className: "relative z-10 px-4 pb-4 text-white",
1282
+ children: [
1283
+ settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
1284
+ /* @__PURE__ */ jsx(
1285
+ "div",
1152
1286
  {
1153
- className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl",
1154
- style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" },
1155
- children: title
1287
+ className: "fixed inset-0 z-70",
1288
+ onClick: closeSettings
1156
1289
  }
1157
1290
  ),
1158
- description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
1159
- ] })
1160
- }
1161
- ),
1162
- /* @__PURE__ */ jsxs(
1163
- "footer",
1164
- {
1165
- onClick: (e) => e.stopPropagation(),
1166
- className: "relative z-10 px-4 pb-4 text-white",
1167
- children: [
1168
- settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
1169
- /* @__PURE__ */ jsx(
1170
- "div",
1171
- {
1172
- className: "fixed inset-0 z-70",
1173
- onClick: closeSettings
1174
- }
1175
- ),
1176
- /* @__PURE__ */ jsxs(
1177
- "div",
1178
- {
1179
- 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",
1180
- style: {
1181
- width: Math.min(
1182
- 224,
1183
- Math.max(180, (playerWidth || 640) * 0.22)
1184
- ) + "px",
1185
- opacity: settingsVisible ? 1 : 0,
1186
- transform: settingsVisible ? "translateY(0) scale(1)" : "translateY(8px) scale(0.97)",
1187
- transition: "opacity 0.18s ease, transform 0.18s ease"
1188
- },
1189
- children: [
1190
- settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
1291
+ /* @__PURE__ */ jsx(
1292
+ "div",
1293
+ {
1294
+ ref: settingsPanelRef,
1295
+ 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",
1296
+ style: {
1297
+ width: Math.min(
1298
+ 224,
1299
+ Math.max(180, (playerWidth || 640) * 0.22)
1300
+ ) + "px",
1301
+ opacity: 0
1302
+ },
1303
+ children: /* @__PURE__ */ jsxs("div", { ref: settingsContentRef, children: [
1304
+ settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
1305
+ {
1306
+ id: "quality",
1307
+ label: "Qualidade",
1308
+ value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto"
1309
+ },
1310
+ ...captions.length > 0 ? [
1311
+ {
1312
+ id: "subtitles",
1313
+ label: "Legendas",
1314
+ value: subtitleStyle.track === "off" ? "Desligado" : captions.find(
1315
+ (s) => s.srclang === subtitleStyle.track
1316
+ )?.label ?? subtitleStyle.track
1317
+ }
1318
+ ] : [],
1319
+ ...audioTracks.length > 1 ? [
1320
+ {
1321
+ id: "audio",
1322
+ label: "\xC1udio",
1323
+ value: audioTracks.find(
1324
+ (t) => t.id === selectedAudio
1325
+ )?.label ?? ""
1326
+ }
1327
+ ] : [],
1328
+ {
1329
+ id: "playback",
1330
+ label: "Velocidade",
1331
+ value: playbackRate === 1 ? "Normal" : `${playbackRate}\xD7`
1332
+ }
1333
+ ].map((item) => /* @__PURE__ */ jsxs(
1334
+ "button",
1335
+ {
1336
+ type: "button",
1337
+ onClick: () => setSettingsTab(item.id),
1338
+ 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",
1339
+ children: [
1340
+ /* @__PURE__ */ jsx("span", { className: "text-white/80", children: item.label }),
1341
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-white/40", children: [
1342
+ item.value,
1343
+ /* @__PURE__ */ jsx(
1344
+ "svg",
1345
+ {
1346
+ className: "size-3 opacity-50",
1347
+ viewBox: "0 0 12 12",
1348
+ fill: "none",
1349
+ children: /* @__PURE__ */ jsx(
1350
+ "path",
1351
+ {
1352
+ d: "M4.5 3l3 3-3 3",
1353
+ stroke: "currentColor",
1354
+ strokeWidth: "1.5",
1355
+ strokeLinecap: "round",
1356
+ strokeLinejoin: "round"
1357
+ }
1358
+ )
1359
+ }
1360
+ )
1361
+ ] })
1362
+ ]
1363
+ },
1364
+ item.id
1365
+ )) }),
1366
+ settingsTab === "quality" && /* @__PURE__ */ jsxs("div", { children: [
1367
+ /* @__PURE__ */ jsxs(
1368
+ "button",
1191
1369
  {
1192
- id: "quality",
1193
- label: "Qualidade",
1194
- value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto"
1370
+ type: "button",
1371
+ onClick: () => setSettingsTab("root"),
1372
+ 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",
1373
+ children: [
1374
+ /* @__PURE__ */ jsx(
1375
+ "svg",
1376
+ {
1377
+ className: "size-3.5",
1378
+ viewBox: "0 0 12 12",
1379
+ fill: "none",
1380
+ children: /* @__PURE__ */ jsx(
1381
+ "path",
1382
+ {
1383
+ d: "M7.5 3L4.5 6l3 3",
1384
+ stroke: "currentColor",
1385
+ strokeWidth: "1.5",
1386
+ strokeLinecap: "round",
1387
+ strokeLinejoin: "round"
1388
+ }
1389
+ )
1390
+ }
1391
+ ),
1392
+ "Qualidade"
1393
+ ]
1394
+ }
1395
+ ),
1396
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
1397
+ "button",
1398
+ {
1399
+ type: "button",
1400
+ onClick: () => {
1401
+ changeQuality(quality.id);
1402
+ setSettingsTab("root");
1403
+ },
1404
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1405
+ children: [
1406
+ /* @__PURE__ */ jsx(
1407
+ "svg",
1408
+ {
1409
+ className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`,
1410
+ viewBox: "0 0 16 16",
1411
+ fill: "none",
1412
+ children: /* @__PURE__ */ jsx(
1413
+ "path",
1414
+ {
1415
+ d: "M3 8l3.5 3.5L13 4.5",
1416
+ stroke: "currentColor",
1417
+ strokeWidth: "1.8",
1418
+ strokeLinecap: "round",
1419
+ strokeLinejoin: "round"
1420
+ }
1421
+ )
1422
+ }
1423
+ ),
1424
+ /* @__PURE__ */ jsxs(
1425
+ "span",
1426
+ {
1427
+ className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55",
1428
+ children: [
1429
+ quality.label,
1430
+ quality.id === "auto" ? " (ABR)" : ""
1431
+ ]
1432
+ }
1433
+ )
1434
+ ]
1195
1435
  },
1196
- ...captions.length > 0 ? [
1197
- {
1198
- id: "subtitles",
1199
- label: "Legendas",
1200
- value: subtitleStyle.track === "off" ? "Desligado" : captions.find(
1201
- (s) => s.srclang === subtitleStyle.track
1202
- )?.label ?? subtitleStyle.track
1203
- }
1204
- ] : [],
1205
- ...audioTracks.length > 1 ? [
1206
- {
1207
- id: "audio",
1208
- label: "\xC1udio",
1209
- value: audioTracks.find(
1210
- (t) => t.id === selectedAudio
1211
- )?.label ?? ""
1212
- }
1213
- ] : [],
1436
+ quality.id
1437
+ )) })
1438
+ ] }),
1439
+ settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
1440
+ /* @__PURE__ */ jsxs(
1441
+ "button",
1214
1442
  {
1215
- id: "playback",
1216
- label: "Velocidade",
1217
- value: playbackRate === 1 ? "Normal" : `${playbackRate}\xD7`
1443
+ type: "button",
1444
+ onClick: () => setSettingsTab("root"),
1445
+ 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",
1446
+ children: [
1447
+ /* @__PURE__ */ jsx(
1448
+ "svg",
1449
+ {
1450
+ className: "size-3.5",
1451
+ viewBox: "0 0 12 12",
1452
+ fill: "none",
1453
+ children: /* @__PURE__ */ jsx(
1454
+ "path",
1455
+ {
1456
+ d: "M7.5 3L4.5 6l3 3",
1457
+ stroke: "currentColor",
1458
+ strokeWidth: "1.5",
1459
+ strokeLinecap: "round",
1460
+ strokeLinejoin: "round"
1461
+ }
1462
+ )
1463
+ }
1464
+ ),
1465
+ "Legendas"
1466
+ ]
1218
1467
  }
1219
- ].map((item) => /* @__PURE__ */ jsxs(
1468
+ ),
1469
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [
1470
+ { srclang: "off", label: "Desligado" },
1471
+ ...captions
1472
+ ].map((s) => /* @__PURE__ */ jsxs(
1220
1473
  "button",
1221
1474
  {
1222
1475
  type: "button",
1223
- onClick: () => setSettingsTab(item.id),
1224
- 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",
1476
+ onClick: () => {
1477
+ const next = s.srclang === "off" ? "off" : s.srclang;
1478
+ setSubtitleMode(next);
1479
+ setSubtitleStyle((st) => ({
1480
+ ...st,
1481
+ track: next
1482
+ }));
1483
+ },
1484
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1225
1485
  children: [
1226
- /* @__PURE__ */ jsx("span", { className: "text-white/80", children: item.label }),
1227
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-white/40", children: [
1228
- item.value,
1229
- /* @__PURE__ */ jsx(
1230
- "svg",
1231
- {
1232
- className: "size-3 opacity-50",
1233
- viewBox: "0 0 12 12",
1234
- fill: "none",
1235
- children: /* @__PURE__ */ jsx(
1236
- "path",
1237
- {
1238
- d: "M4.5 3l3 3-3 3",
1239
- stroke: "currentColor",
1240
- strokeWidth: "1.5",
1241
- strokeLinecap: "round",
1242
- strokeLinejoin: "round"
1243
- }
1244
- )
1245
- }
1246
- )
1247
- ] })
1486
+ /* @__PURE__ */ jsx(
1487
+ "svg",
1488
+ {
1489
+ className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`,
1490
+ viewBox: "0 0 16 16",
1491
+ fill: "none",
1492
+ children: /* @__PURE__ */ jsx(
1493
+ "path",
1494
+ {
1495
+ d: "M3 8l3.5 3.5L13 4.5",
1496
+ stroke: "currentColor",
1497
+ strokeWidth: "1.8",
1498
+ strokeLinecap: "round",
1499
+ strokeLinejoin: "round"
1500
+ }
1501
+ )
1502
+ }
1503
+ ),
1504
+ /* @__PURE__ */ jsx(
1505
+ "span",
1506
+ {
1507
+ className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55",
1508
+ children: s.label
1509
+ }
1510
+ )
1248
1511
  ]
1249
1512
  },
1250
- item.id
1513
+ s.srclang
1251
1514
  )) }),
1252
- settingsTab === "quality" && /* @__PURE__ */ jsxs("div", { children: [
1253
- /* @__PURE__ */ jsxs(
1254
- "button",
1255
- {
1256
- type: "button",
1257
- onClick: () => setSettingsTab("root"),
1258
- 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",
1259
- children: [
1260
- /* @__PURE__ */ jsx(
1261
- "svg",
1262
- {
1263
- className: "size-3.5",
1264
- viewBox: "0 0 12 12",
1265
- fill: "none",
1266
- children: /* @__PURE__ */ jsx(
1267
- "path",
1268
- {
1269
- d: "M7.5 3L4.5 6l3 3",
1270
- stroke: "currentColor",
1271
- strokeWidth: "1.5",
1272
- strokeLinecap: "round",
1273
- strokeLinejoin: "round"
1274
- }
1275
- )
1276
- }
1277
- ),
1278
- "Qualidade"
1279
- ]
1280
- }
1281
- ),
1282
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
1283
- "button",
1284
- {
1285
- type: "button",
1286
- onClick: () => {
1287
- changeQuality(quality.id);
1288
- setSettingsTab("root");
1515
+ subtitleStyle.track !== "off" && /* @__PURE__ */ jsxs(
1516
+ "button",
1517
+ {
1518
+ type: "button",
1519
+ onClick: () => setSettingsTab("subtitles-style"),
1520
+ 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",
1521
+ children: [
1522
+ /* @__PURE__ */ jsx("span", { className: "text-white/60", children: "Apar\xEAncia" }),
1523
+ /* @__PURE__ */ jsx(
1524
+ "svg",
1525
+ {
1526
+ className: "size-3 opacity-50",
1527
+ viewBox: "0 0 12 12",
1528
+ fill: "none",
1529
+ children: /* @__PURE__ */ jsx(
1530
+ "path",
1531
+ {
1532
+ d: "M4.5 3l3 3-3 3",
1533
+ stroke: "currentColor",
1534
+ strokeWidth: "1.5",
1535
+ strokeLinecap: "round",
1536
+ strokeLinejoin: "round"
1537
+ }
1538
+ )
1539
+ }
1540
+ )
1541
+ ]
1542
+ }
1543
+ )
1544
+ ] }),
1545
+ settingsTab === "subtitles-style" && /* @__PURE__ */ jsxs("div", { children: [
1546
+ /* @__PURE__ */ jsxs(
1547
+ "button",
1548
+ {
1549
+ type: "button",
1550
+ onClick: () => setSettingsTab("subtitles"),
1551
+ 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",
1552
+ children: [
1553
+ /* @__PURE__ */ jsx(
1554
+ "svg",
1555
+ {
1556
+ className: "size-3.5",
1557
+ viewBox: "0 0 12 12",
1558
+ fill: "none",
1559
+ children: /* @__PURE__ */ jsx(
1560
+ "path",
1561
+ {
1562
+ d: "M7.5 3L4.5 6l3 3",
1563
+ stroke: "currentColor",
1564
+ strokeWidth: "1.5",
1565
+ strokeLinecap: "round",
1566
+ strokeLinejoin: "round"
1567
+ }
1568
+ )
1569
+ }
1570
+ ),
1571
+ "Apar\xEAncia"
1572
+ ]
1573
+ }
1574
+ ),
1575
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex flex-col gap-3", children: [
1576
+ /* @__PURE__ */ jsxs("div", { children: [
1577
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Tamanho" }),
1578
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
1579
+ "button",
1580
+ {
1581
+ type: "button",
1582
+ onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
1583
+ 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"}`,
1584
+ children: s === "small" ? "P" : s === "medium" ? "M" : s === "large" ? "G" : "GG"
1289
1585
  },
1290
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1291
- children: [
1292
- /* @__PURE__ */ jsx(
1293
- "svg",
1294
- {
1295
- className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`,
1296
- viewBox: "0 0 16 16",
1297
- fill: "none",
1298
- children: /* @__PURE__ */ jsx(
1299
- "path",
1300
- {
1301
- d: "M3 8l3.5 3.5L13 4.5",
1302
- stroke: "currentColor",
1303
- strokeWidth: "1.8",
1304
- strokeLinecap: "round",
1305
- strokeLinejoin: "round"
1306
- }
1307
- )
1308
- }
1309
- ),
1310
- /* @__PURE__ */ jsxs(
1311
- "span",
1312
- {
1313
- className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55",
1314
- children: [
1315
- quality.label,
1316
- quality.id === "auto" ? " (ABR)" : ""
1317
- ]
1318
- }
1319
- )
1320
- ]
1321
- },
1322
- quality.id
1323
- )) })
1324
- ] }),
1325
- settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
1326
- /* @__PURE__ */ jsxs(
1327
- "button",
1328
- {
1329
- type: "button",
1330
- onClick: () => setSettingsTab("root"),
1331
- 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",
1332
- children: [
1333
- /* @__PURE__ */ jsx(
1334
- "svg",
1335
- {
1336
- className: "size-3.5",
1337
- viewBox: "0 0 12 12",
1338
- fill: "none",
1339
- children: /* @__PURE__ */ jsx(
1340
- "path",
1341
- {
1342
- d: "M7.5 3L4.5 6l3 3",
1343
- stroke: "currentColor",
1344
- strokeWidth: "1.5",
1345
- strokeLinecap: "round",
1346
- strokeLinejoin: "round"
1347
- }
1348
- )
1349
- }
1350
- ),
1351
- "Legendas"
1352
- ]
1353
- }
1354
- ),
1355
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [
1356
- { srclang: "off", label: "Desligado" },
1357
- ...captions
1358
- ].map((s) => /* @__PURE__ */ jsxs(
1359
- "button",
1360
- {
1361
- type: "button",
1362
- onClick: () => {
1363
- const next = s.srclang === "off" ? "off" : s.srclang;
1364
- setSubtitleMode(next);
1365
- setSubtitleStyle((st) => ({
1586
+ s
1587
+ )) })
1588
+ ] }),
1589
+ /* @__PURE__ */ jsxs("div", { children: [
1590
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Cor" }),
1591
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
1592
+ ["white", "Branco", "#fff"],
1593
+ ["yellow", "Amarelo", "#facc15"],
1594
+ ["cyan", "Ciano", "#22d3ee"]
1595
+ ].map(([val, label, color]) => /* @__PURE__ */ jsx(
1596
+ "button",
1597
+ {
1598
+ type: "button",
1599
+ onClick: () => setSubtitleStyle((st) => ({
1366
1600
  ...st,
1367
- track: next
1368
- }));
1601
+ color: val
1602
+ })),
1603
+ 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"}`,
1604
+ style: { color },
1605
+ children: label
1369
1606
  },
1370
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1371
- children: [
1372
- /* @__PURE__ */ jsx(
1373
- "svg",
1374
- {
1375
- className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`,
1376
- viewBox: "0 0 16 16",
1377
- fill: "none",
1378
- children: /* @__PURE__ */ jsx(
1379
- "path",
1380
- {
1381
- d: "M3 8l3.5 3.5L13 4.5",
1382
- stroke: "currentColor",
1383
- strokeWidth: "1.8",
1384
- strokeLinecap: "round",
1385
- strokeLinejoin: "round"
1386
- }
1387
- )
1388
- }
1389
- ),
1390
- /* @__PURE__ */ jsx(
1391
- "span",
1392
- {
1393
- className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55",
1394
- children: s.label
1395
- }
1396
- )
1397
- ]
1607
+ val
1608
+ )) })
1609
+ ] }),
1610
+ /* @__PURE__ */ jsxs("div", { children: [
1611
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Fundo" }),
1612
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
1613
+ ["none", "Nenhum"],
1614
+ ["semi", "Semi"],
1615
+ ["solid", "S\xF3lido"]
1616
+ ].map(([val, label]) => /* @__PURE__ */ jsx(
1617
+ "button",
1618
+ {
1619
+ type: "button",
1620
+ onClick: () => setSubtitleStyle((st) => ({ ...st, bg: val })),
1621
+ 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"}`,
1622
+ children: label
1623
+ },
1624
+ val
1625
+ )) })
1626
+ ] })
1627
+ ] })
1628
+ ] }),
1629
+ settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
1630
+ /* @__PURE__ */ jsxs(
1631
+ "button",
1632
+ {
1633
+ type: "button",
1634
+ onClick: () => setSettingsTab("root"),
1635
+ 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",
1636
+ children: [
1637
+ /* @__PURE__ */ jsx(
1638
+ "svg",
1639
+ {
1640
+ className: "size-3.5",
1641
+ viewBox: "0 0 12 12",
1642
+ fill: "none",
1643
+ children: /* @__PURE__ */ jsx(
1644
+ "path",
1645
+ {
1646
+ d: "M7.5 3L4.5 6l3 3",
1647
+ stroke: "currentColor",
1648
+ strokeWidth: "1.5",
1649
+ strokeLinecap: "round",
1650
+ strokeLinejoin: "round"
1651
+ }
1652
+ )
1653
+ }
1654
+ ),
1655
+ "\xC1udio"
1656
+ ]
1657
+ }
1658
+ ),
1659
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
1660
+ "button",
1661
+ {
1662
+ type: "button",
1663
+ onClick: () => {
1664
+ changeAudio(track.id);
1665
+ setSettingsTab("root");
1398
1666
  },
1399
- s.srclang
1400
- )) }),
1401
- subtitleStyle.track !== "off" && /* @__PURE__ */ jsxs(
1402
- "button",
1403
- {
1404
- type: "button",
1405
- onClick: () => setSettingsTab("subtitles-style"),
1406
- 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",
1407
- children: [
1408
- /* @__PURE__ */ jsx("span", { className: "text-white/60", children: "Apar\xEAncia" }),
1409
- /* @__PURE__ */ jsx(
1410
- "svg",
1411
- {
1412
- className: "size-3 opacity-50",
1413
- viewBox: "0 0 12 12",
1414
- fill: "none",
1415
- children: /* @__PURE__ */ jsx(
1416
- "path",
1417
- {
1418
- d: "M4.5 3l3 3-3 3",
1419
- stroke: "currentColor",
1420
- strokeWidth: "1.5",
1421
- strokeLinecap: "round",
1422
- strokeLinejoin: "round"
1423
- }
1424
- )
1425
- }
1426
- )
1427
- ]
1428
- }
1429
- )
1430
- ] }),
1431
- settingsTab === "subtitles-style" && /* @__PURE__ */ jsxs("div", { children: [
1432
- /* @__PURE__ */ jsxs(
1433
- "button",
1434
- {
1435
- type: "button",
1436
- onClick: () => setSettingsTab("subtitles"),
1437
- 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",
1438
- children: [
1439
- /* @__PURE__ */ jsx(
1440
- "svg",
1441
- {
1442
- className: "size-3.5",
1443
- viewBox: "0 0 12 12",
1444
- fill: "none",
1445
- children: /* @__PURE__ */ jsx(
1446
- "path",
1447
- {
1448
- d: "M7.5 3L4.5 6l3 3",
1449
- stroke: "currentColor",
1450
- strokeWidth: "1.5",
1451
- strokeLinecap: "round",
1452
- strokeLinejoin: "round"
1453
- }
1454
- )
1455
- }
1456
- ),
1457
- "Apar\xEAncia"
1458
- ]
1459
- }
1460
- ),
1461
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex flex-col gap-3", children: [
1462
- /* @__PURE__ */ jsxs("div", { children: [
1463
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Tamanho" }),
1464
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
1465
- "button",
1667
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1668
+ children: [
1669
+ /* @__PURE__ */ jsx(
1670
+ "svg",
1466
1671
  {
1467
- type: "button",
1468
- onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
1469
- 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"}`,
1470
- children: s === "small" ? "P" : s === "medium" ? "M" : s === "large" ? "G" : "GG"
1471
- },
1472
- s
1473
- )) })
1474
- ] }),
1475
- /* @__PURE__ */ jsxs("div", { children: [
1476
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Cor" }),
1477
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
1478
- ["white", "Branco", "#fff"],
1479
- ["yellow", "Amarelo", "#facc15"],
1480
- ["cyan", "Ciano", "#22d3ee"]
1481
- ].map(([val, label, color]) => /* @__PURE__ */ jsx(
1482
- "button",
1672
+ className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`,
1673
+ viewBox: "0 0 16 16",
1674
+ fill: "none",
1675
+ children: /* @__PURE__ */ jsx(
1676
+ "path",
1677
+ {
1678
+ d: "M3 8l3.5 3.5L13 4.5",
1679
+ stroke: "currentColor",
1680
+ strokeWidth: "1.8",
1681
+ strokeLinecap: "round",
1682
+ strokeLinejoin: "round"
1683
+ }
1684
+ )
1685
+ }
1686
+ ),
1687
+ /* @__PURE__ */ jsx(
1688
+ "span",
1483
1689
  {
1484
- type: "button",
1485
- onClick: () => setSubtitleStyle((st) => ({
1486
- ...st,
1487
- color: val
1488
- })),
1489
- 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"}`,
1490
- style: { color },
1491
- children: label
1492
- },
1493
- val
1494
- )) })
1495
- ] }),
1496
- /* @__PURE__ */ jsxs("div", { children: [
1497
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Fundo" }),
1498
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [
1499
- ["none", "Nenhum"],
1500
- ["semi", "Semi"],
1501
- ["solid", "S\xF3lido"]
1502
- ].map(([val, label]) => /* @__PURE__ */ jsx(
1503
- "button",
1690
+ className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55",
1691
+ children: track.label
1692
+ }
1693
+ )
1694
+ ]
1695
+ },
1696
+ track.id
1697
+ )) })
1698
+ ] }),
1699
+ settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
1700
+ /* @__PURE__ */ jsxs(
1701
+ "button",
1702
+ {
1703
+ type: "button",
1704
+ onClick: () => setSettingsTab("root"),
1705
+ 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",
1706
+ children: [
1707
+ /* @__PURE__ */ jsx(
1708
+ "svg",
1504
1709
  {
1505
- type: "button",
1506
- onClick: () => setSubtitleStyle((st) => ({ ...st, bg: val })),
1507
- 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"}`,
1508
- children: label
1509
- },
1510
- val
1511
- )) })
1512
- ] })
1513
- ] })
1514
- ] }),
1515
- settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
1516
- /* @__PURE__ */ jsxs(
1517
- "button",
1518
- {
1519
- type: "button",
1520
- onClick: () => setSettingsTab("root"),
1521
- 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",
1522
- children: [
1523
- /* @__PURE__ */ jsx(
1524
- "svg",
1525
- {
1526
- className: "size-3.5",
1527
- viewBox: "0 0 12 12",
1528
- fill: "none",
1529
- children: /* @__PURE__ */ jsx(
1530
- "path",
1531
- {
1532
- d: "M7.5 3L4.5 6l3 3",
1533
- stroke: "currentColor",
1534
- strokeWidth: "1.5",
1535
- strokeLinecap: "round",
1536
- strokeLinejoin: "round"
1537
- }
1538
- )
1539
- }
1540
- ),
1541
- "\xC1udio"
1542
- ]
1543
- }
1544
- ),
1545
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
1546
- "button",
1547
- {
1548
- type: "button",
1549
- onClick: () => {
1550
- changeAudio(track.id);
1551
- setSettingsTab("root");
1552
- },
1553
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1554
- children: [
1555
- /* @__PURE__ */ jsx(
1556
- "svg",
1557
- {
1558
- className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`,
1559
- viewBox: "0 0 16 16",
1560
- fill: "none",
1561
- children: /* @__PURE__ */ jsx(
1562
- "path",
1563
- {
1564
- d: "M3 8l3.5 3.5L13 4.5",
1565
- stroke: "currentColor",
1566
- strokeWidth: "1.8",
1567
- strokeLinecap: "round",
1568
- strokeLinejoin: "round"
1569
- }
1570
- )
1571
- }
1572
- ),
1573
- /* @__PURE__ */ jsx(
1574
- "span",
1575
- {
1576
- className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55",
1577
- children: track.label
1578
- }
1579
- )
1580
- ]
1710
+ className: "size-3.5",
1711
+ viewBox: "0 0 12 12",
1712
+ fill: "none",
1713
+ children: /* @__PURE__ */ jsx(
1714
+ "path",
1715
+ {
1716
+ d: "M7.5 3L4.5 6l3 3",
1717
+ stroke: "currentColor",
1718
+ strokeWidth: "1.5",
1719
+ strokeLinecap: "round",
1720
+ strokeLinejoin: "round"
1721
+ }
1722
+ )
1723
+ }
1724
+ ),
1725
+ "Velocidade"
1726
+ ]
1727
+ }
1728
+ ),
1729
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsxs(
1730
+ "button",
1731
+ {
1732
+ type: "button",
1733
+ onClick: () => {
1734
+ setPlaybackRate(speed);
1735
+ closeSettings();
1581
1736
  },
1582
- track.id
1583
- )) })
1584
- ] }),
1585
- settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
1586
- /* @__PURE__ */ jsxs(
1587
- "button",
1737
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1738
+ children: [
1739
+ /* @__PURE__ */ jsx(
1740
+ "svg",
1741
+ {
1742
+ className: `size-4 shrink-0 ${playbackRate === speed ? "text-white" : "text-transparent"}`,
1743
+ viewBox: "0 0 16 16",
1744
+ fill: "none",
1745
+ children: /* @__PURE__ */ jsx(
1746
+ "path",
1747
+ {
1748
+ d: "M3 8l3.5 3.5L13 4.5",
1749
+ stroke: "currentColor",
1750
+ strokeWidth: "1.8",
1751
+ strokeLinecap: "round",
1752
+ strokeLinejoin: "round"
1753
+ }
1754
+ )
1755
+ }
1756
+ ),
1757
+ /* @__PURE__ */ jsx(
1758
+ "span",
1759
+ {
1760
+ className: playbackRate === speed ? "font-semibold text-white" : "text-white/55",
1761
+ children: speed === 1 ? "Normal" : `${speed}\xD7`
1762
+ }
1763
+ )
1764
+ ]
1765
+ },
1766
+ speed
1767
+ )) })
1768
+ ] })
1769
+ ] })
1770
+ }
1771
+ )
1772
+ ] }),
1773
+ /* @__PURE__ */ jsxs(
1774
+ "div",
1775
+ {
1776
+ ref: progressRef,
1777
+ onPointerMove: handleProgressPointerMove,
1778
+ onPointerEnter: handleProgressPointerEnter,
1779
+ onPointerLeave: handleProgressPointerLeave,
1780
+ onPointerDown: handleProgressPointerDown,
1781
+ onPointerUp: handleProgressPointerUp,
1782
+ className: "relative mb-2 h-8 cursor-pointer overflow-visible",
1783
+ children: [
1784
+ /* @__PURE__ */ jsxs(
1785
+ "div",
1786
+ {
1787
+ ref: progressTrackRef,
1788
+ className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/18",
1789
+ style: {
1790
+ height: "3px"
1791
+ },
1792
+ children: [
1793
+ /* @__PURE__ */ jsx(
1794
+ "div",
1588
1795
  {
1589
- type: "button",
1590
- onClick: () => setSettingsTab("root"),
1591
- 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",
1592
- children: [
1593
- /* @__PURE__ */ jsx(
1594
- "svg",
1595
- {
1596
- className: "size-3.5",
1597
- viewBox: "0 0 12 12",
1598
- fill: "none",
1599
- children: /* @__PURE__ */ jsx(
1600
- "path",
1601
- {
1602
- d: "M7.5 3L4.5 6l3 3",
1603
- stroke: "currentColor",
1604
- strokeWidth: "1.5",
1605
- strokeLinecap: "round",
1606
- strokeLinejoin: "round"
1607
- }
1608
- )
1609
- }
1610
- ),
1611
- "Velocidade"
1612
- ]
1796
+ className: "absolute inset-y-0 left-0 rounded-full bg-white/28",
1797
+ style: { width: `${bufferedPercent}%` }
1613
1798
  }
1614
1799
  ),
1615
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsxs(
1616
- "button",
1800
+ /* @__PURE__ */ jsx(
1801
+ "div",
1617
1802
  {
1618
- type: "button",
1619
- onClick: () => {
1620
- setPlaybackRate(speed);
1621
- closeSettings();
1622
- },
1623
- className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
1624
- children: [
1625
- /* @__PURE__ */ jsx(
1626
- "svg",
1627
- {
1628
- className: `size-4 shrink-0 ${playbackRate === speed ? "text-white" : "text-transparent"}`,
1629
- viewBox: "0 0 16 16",
1630
- fill: "none",
1631
- children: /* @__PURE__ */ jsx(
1632
- "path",
1633
- {
1634
- d: "M3 8l3.5 3.5L13 4.5",
1635
- stroke: "currentColor",
1636
- strokeWidth: "1.8",
1637
- strokeLinecap: "round",
1638
- strokeLinejoin: "round"
1639
- }
1640
- )
1641
- }
1642
- ),
1643
- /* @__PURE__ */ jsx(
1644
- "span",
1645
- {
1646
- className: playbackRate === speed ? "font-semibold text-white" : "text-white/55",
1647
- children: speed === 1 ? "Normal" : `${speed}\xD7`
1648
- }
1649
- )
1650
- ]
1651
- },
1652
- speed
1653
- )) })
1654
- ] })
1655
- ]
1656
- }
1657
- )
1658
- ] }),
1659
- /* @__PURE__ */ jsxs(
1660
- "div",
1661
- {
1662
- ref: progressRef,
1663
- onPointerMove: handleProgressPointerMove,
1664
- onPointerEnter: handleProgressPointerEnter,
1665
- onPointerLeave: handleProgressPointerLeave,
1666
- onPointerDown: handleProgressPointerDown,
1667
- onPointerUp: handleProgressPointerUp,
1668
- className: "relative mb-2 h-8 cursor-pointer overflow-visible",
1669
- children: [
1670
- /* @__PURE__ */ jsxs(
1803
+ className: "absolute inset-y-0 left-0 rounded-full bg-white",
1804
+ style: { width: `${progressPercent}%`, transition: "width 0.05s linear" }
1805
+ }
1806
+ )
1807
+ ]
1808
+ }
1809
+ ),
1810
+ /* @__PURE__ */ jsx(
1811
+ "div",
1812
+ {
1813
+ ref: progressThumbRef,
1814
+ className: "pointer-events-none absolute rounded-full bg-white shadow-[0_1px_6px_rgba(0,0,0,0.5)]",
1815
+ style: {
1816
+ top: "50%",
1817
+ left: `${progressPercent}%`,
1818
+ transform: "translate(-50%, -50%)",
1819
+ width: "10px",
1820
+ height: "10px"
1821
+ }
1822
+ }
1823
+ ),
1824
+ chapters.length > 0 && duration > 0 && chapters.map((ch, i) => /* @__PURE__ */ jsx(
1825
+ "div",
1826
+ {
1827
+ "data-chapter-marker": true,
1828
+ className: "pointer-events-none absolute top-1/2 -translate-y-1/2 w-0.5 rounded-full bg-white/50",
1829
+ style: { left: `${ch.startTime / duration * 100}%`, height: "3px" }
1830
+ },
1831
+ i
1832
+ )),
1833
+ preview && (() => {
1834
+ const frameW = preview.cue.w ?? 160;
1835
+ const frameH = preview.cue.h ?? 90;
1836
+ const thumbW = 200;
1837
+ const thumbH = Math.round(thumbW * (frameH / frameW));
1838
+ const scale = thumbW / frameW;
1839
+ const isSprite = preview.cue.x != null && preview.cue.y != null;
1840
+ return /* @__PURE__ */ jsxs(
1671
1841
  "div",
1672
1842
  {
1673
- className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/18",
1843
+ className: "pointer-events-none absolute flex flex-col items-center gap-1",
1674
1844
  style: {
1675
- height: isDragging ? "7px" : isHoveringProgress ? "5px" : "3px",
1676
- transition: "height 0.15s ease"
1845
+ bottom: "calc(100% + 6px)",
1846
+ left: preview.left,
1847
+ transform: "translateX(-50%)",
1848
+ zIndex: 80
1677
1849
  },
1678
1850
  children: [
1679
1851
  /* @__PURE__ */ jsx(
1680
1852
  "div",
1681
1853
  {
1682
- className: "absolute inset-y-0 left-0 rounded-full bg-white/28",
1683
- style: { width: `${bufferedPercent}%` }
1854
+ className: "overflow-hidden rounded-lg shadow-2xl ring-1 ring-white/20",
1855
+ style: { width: thumbW, height: thumbH, flexShrink: 0 },
1856
+ children: isSprite ? (
1857
+ // Sprite: need full sheet dimensions to compute backgroundSize correctly.
1858
+ // Load them once from the image's natural size.
1859
+ (() => {
1860
+ const imgUrl = preview.cue.image;
1861
+ if (storyboardSheetUrlRef.current !== imgUrl) {
1862
+ storyboardSheetUrlRef.current = imgUrl;
1863
+ const img = new window.Image();
1864
+ img.onload = () => setStoryboardSheetSize({ w: img.naturalWidth, h: img.naturalHeight });
1865
+ img.src = imgUrl;
1866
+ }
1867
+ if (!storyboardSheetSize) return null;
1868
+ const bsW = storyboardSheetSize.w * scale;
1869
+ const bsH = storyboardSheetSize.h * scale;
1870
+ return /* @__PURE__ */ jsx(
1871
+ "div",
1872
+ {
1873
+ style: {
1874
+ width: thumbW,
1875
+ height: thumbH,
1876
+ backgroundImage: `url(${imgUrl})`,
1877
+ backgroundRepeat: "no-repeat",
1878
+ backgroundPosition: `-${(preview.cue.x ?? 0) * scale}px -${(preview.cue.y ?? 0) * scale}px`,
1879
+ backgroundSize: `${bsW}px ${bsH}px`
1880
+ }
1881
+ }
1882
+ );
1883
+ })()
1884
+ ) : /* @__PURE__ */ jsx(
1885
+ "img",
1886
+ {
1887
+ src: preview.cue.image,
1888
+ alt: "",
1889
+ style: { width: thumbW, height: thumbH, objectFit: "cover", objectPosition: "center", display: "block" }
1890
+ }
1891
+ )
1684
1892
  }
1685
1893
  ),
1686
- /* @__PURE__ */ jsx(
1894
+ /* @__PURE__ */ jsxs(
1687
1895
  "div",
1688
1896
  {
1689
- className: "absolute inset-y-0 left-0 rounded-full bg-white",
1690
- style: { width: `${progressPercent}%`, transition: "width 0.05s linear" }
1897
+ className: "flex items-center gap-1.5 rounded-md px-2 py-0.5 text-[11px] font-semibold text-white/90",
1898
+ style: { background: "rgba(0,0,0,0.55)", backdropFilter: "blur(6px)" },
1899
+ children: [
1900
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatTime(preview.time) }),
1901
+ (() => {
1902
+ const ch = [...chapters].reverse().find((c) => c.startTime <= preview.time);
1903
+ return ch ? /* @__PURE__ */ jsxs(Fragment, { children: [
1904
+ /* @__PURE__ */ jsx("span", { className: "text-white/40", children: "\xB7" }),
1905
+ /* @__PURE__ */ jsx("span", { className: "max-w-36 truncate", children: ch.title })
1906
+ ] }) : null;
1907
+ })()
1908
+ ]
1691
1909
  }
1692
1910
  )
1693
1911
  ]
1694
1912
  }
1695
- ),
1696
- /* @__PURE__ */ jsx(
1697
- "div",
1698
- {
1699
- className: "pointer-events-none absolute rounded-full bg-white shadow-[0_1px_6px_rgba(0,0,0,0.5)]",
1700
- style: {
1701
- top: "50%",
1702
- left: `${progressPercent}%`,
1703
- transform: "translate(-50%, -50%)",
1704
- width: isDragging ? "18px" : isHoveringProgress ? "14px" : "10px",
1705
- height: isDragging ? "18px" : isHoveringProgress ? "14px" : "10px",
1706
- 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)"
1707
- }
1708
- }
1709
- ),
1710
- chapters.length > 0 && duration > 0 && chapters.map((ch, i) => /* @__PURE__ */ jsx(
1711
- "div",
1712
- {
1713
- className: "pointer-events-none absolute top-1/2 -translate-y-1/2 w-0.5 rounded-full bg-white/50",
1714
- style: { left: `${ch.startTime / duration * 100}%`, height: isDragging ? "7px" : isHoveringProgress ? "5px" : "3px", transition: "height 0.15s ease" }
1715
- },
1716
- i
1717
- )),
1718
- preview && (() => {
1719
- const frameW = preview.cue.w ?? 160;
1720
- const frameH = preview.cue.h ?? 90;
1721
- const thumbW = 200;
1722
- const thumbH = Math.round(thumbW * (frameH / frameW));
1723
- const scale = thumbW / frameW;
1724
- const isSprite = preview.cue.x != null && preview.cue.y != null;
1913
+ );
1914
+ })()
1915
+ ]
1916
+ }
1917
+ ),
1918
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1919
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 @sm:gap-2", children: [
1920
+ /* @__PURE__ */ jsx(
1921
+ "button",
1922
+ {
1923
+ type: "button",
1924
+ onClick: togglePlay,
1925
+ className: "grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10 @sm:size-9",
1926
+ "aria-label": isPlaying ? "Pause" : "Play",
1927
+ 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" })
1928
+ }
1929
+ ),
1930
+ /* @__PURE__ */ jsxs("span", { className: "text-[11px] font-medium tabular-nums text-white/80", children: [
1931
+ formatTime(currentTime),
1932
+ /* @__PURE__ */ jsx("span", { className: "text-white/30", children: "/" }),
1933
+ /* @__PURE__ */ jsx("span", { className: "text-white/45", children: formatTime(duration) })
1934
+ ] }),
1935
+ (() => {
1936
+ if (chapters.length === 0) return null;
1937
+ const ch = [...chapters].reverse().find((c) => currentTime >= c.startTime);
1938
+ return ch ? /* @__PURE__ */ jsx("span", { className: "hidden max-w-40 truncate text-[11px] text-white/50 @sm:block", children: ch.title }) : null;
1939
+ })()
1940
+ ] }),
1941
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 @sm:gap-1", children: [
1942
+ parsed.rating && (() => {
1943
+ const REACTIONS = [
1944
+ { key: "LOVE", emoji: "\u2764\uFE0F" },
1945
+ { key: "LIKE", emoji: "\u{1F44D}" },
1946
+ { key: "DISLIKE", emoji: "\u{1F44E}" }
1947
+ ];
1948
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1949
+ REACTIONS.map(({ key, emoji }) => {
1950
+ const count = ratingCounts[key] ?? 0;
1951
+ const active = userReaction === key;
1725
1952
  return /* @__PURE__ */ jsxs(
1726
- "div",
1953
+ "button",
1727
1954
  {
1728
- className: "pointer-events-none absolute flex flex-col items-center gap-1",
1729
- style: {
1730
- bottom: "calc(100% + 6px)",
1731
- left: preview.left,
1732
- transform: "translateX(-50%)",
1733
- zIndex: 80
1955
+ type: "button",
1956
+ onClick: (e) => {
1957
+ e.stopPropagation();
1958
+ const next = active ? null : key;
1959
+ setUserReaction(next);
1960
+ setRatingCounts((prev) => {
1961
+ const updated = { ...prev };
1962
+ const prev_reaction = userReactionRef.current;
1963
+ if (active) updated[key] = Math.max(0, (updated[key] ?? 0) - 1);
1964
+ else {
1965
+ if (prev_reaction) updated[prev_reaction] = Math.max(0, (updated[prev_reaction] ?? 0) - 1);
1966
+ updated[key] = (updated[key] ?? 0) + 1;
1967
+ }
1968
+ return updated;
1969
+ });
1970
+ onReactRef.current?.(next);
1734
1971
  },
1972
+ 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"}`,
1973
+ "aria-label": key.toLowerCase(),
1974
+ "aria-pressed": active,
1735
1975
  children: [
1736
- /* @__PURE__ */ jsx(
1737
- "div",
1738
- {
1739
- className: "overflow-hidden rounded-lg shadow-2xl ring-1 ring-white/20",
1740
- style: { width: thumbW, height: thumbH, flexShrink: 0 },
1741
- children: isSprite ? (
1742
- // Sprite: need full sheet dimensions to compute backgroundSize correctly.
1743
- // Load them once from the image's natural size.
1744
- (() => {
1745
- const imgUrl = preview.cue.image;
1746
- if (storyboardSheetUrlRef.current !== imgUrl) {
1747
- storyboardSheetUrlRef.current = imgUrl;
1748
- const img = new window.Image();
1749
- img.onload = () => setStoryboardSheetSize({ w: img.naturalWidth, h: img.naturalHeight });
1750
- img.src = imgUrl;
1751
- }
1752
- if (!storyboardSheetSize) return null;
1753
- const bsW = storyboardSheetSize.w * scale;
1754
- const bsH = storyboardSheetSize.h * scale;
1755
- return /* @__PURE__ */ jsx(
1756
- "div",
1757
- {
1758
- style: {
1759
- width: thumbW,
1760
- height: thumbH,
1761
- backgroundImage: `url(${imgUrl})`,
1762
- backgroundRepeat: "no-repeat",
1763
- backgroundPosition: `-${(preview.cue.x ?? 0) * scale}px -${(preview.cue.y ?? 0) * scale}px`,
1764
- backgroundSize: `${bsW}px ${bsH}px`
1765
- }
1766
- }
1767
- );
1768
- })()
1769
- ) : /* @__PURE__ */ jsx(
1770
- "img",
1771
- {
1772
- src: preview.cue.image,
1773
- alt: "",
1774
- style: { width: thumbW, height: thumbH, objectFit: "cover", objectPosition: "center", display: "block" }
1775
- }
1776
- )
1777
- }
1778
- ),
1779
- /* @__PURE__ */ jsxs(
1780
- "div",
1781
- {
1782
- className: "flex items-center gap-1.5 rounded-md px-2 py-0.5 text-[11px] font-semibold text-white/90",
1783
- style: { background: "rgba(0,0,0,0.55)", backdropFilter: "blur(6px)" },
1784
- children: [
1785
- /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatTime(preview.time) }),
1786
- (() => {
1787
- const ch = [...chapters].reverse().find((c) => c.startTime <= preview.time);
1788
- return ch ? /* @__PURE__ */ jsxs(Fragment, { children: [
1789
- /* @__PURE__ */ jsx("span", { className: "text-white/40", children: "\xB7" }),
1790
- /* @__PURE__ */ jsx("span", { className: "max-w-36 truncate", children: ch.title })
1791
- ] }) : null;
1792
- })()
1793
- ]
1794
- }
1795
- )
1976
+ /* @__PURE__ */ jsx("span", { children: emoji }),
1977
+ count > 0 && /* @__PURE__ */ jsx("span", { className: "text-white/70 tabular-nums", children: count })
1796
1978
  ]
1797
- }
1979
+ },
1980
+ key
1798
1981
  );
1799
- })()
1800
- ]
1801
- }
1802
- ),
1803
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1804
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 @sm:gap-2", children: [
1805
- /* @__PURE__ */ jsx(
1806
- "button",
1807
- {
1808
- type: "button",
1809
- onClick: togglePlay,
1810
- className: "grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10 @sm:size-9",
1811
- "aria-label": isPlaying ? "Pause" : "Play",
1812
- 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" })
1813
- }
1814
- ),
1815
- /* @__PURE__ */ jsxs("span", { className: "text-[11px] font-medium tabular-nums text-white/80", children: [
1816
- formatTime(currentTime),
1817
- /* @__PURE__ */ jsx("span", { className: "text-white/30", children: "/" }),
1818
- /* @__PURE__ */ jsx("span", { className: "text-white/45", children: formatTime(duration) })
1819
- ] }),
1820
- (() => {
1821
- if (chapters.length === 0) return null;
1822
- const ch = [...chapters].reverse().find((c) => currentTime >= c.startTime);
1823
- return ch ? /* @__PURE__ */ jsx("span", { className: "hidden max-w-40 truncate text-[11px] text-white/50 @sm:block", children: ch.title }) : null;
1824
- })()
1825
- ] }),
1826
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 @sm:gap-1", children: [
1827
- parsed.rating && (() => {
1828
- const REACTIONS = [
1829
- { key: "LOVE", emoji: "\u2764\uFE0F" },
1830
- { key: "LIKE", emoji: "\u{1F44D}" },
1831
- { key: "DISLIKE", emoji: "\u{1F44E}" }
1832
- ];
1833
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1834
- REACTIONS.map(({ key, emoji }) => {
1835
- const count = ratingCounts[key] ?? 0;
1836
- const active = userReaction === key;
1837
- return /* @__PURE__ */ jsxs(
1838
- "button",
1839
- {
1840
- type: "button",
1841
- onClick: (e) => {
1842
- e.stopPropagation();
1843
- const next = active ? null : key;
1844
- setUserReaction(next);
1845
- setRatingCounts((prev) => {
1846
- const updated = { ...prev };
1847
- const prev_reaction = userReactionRef.current;
1848
- if (active) updated[key] = Math.max(0, (updated[key] ?? 0) - 1);
1849
- else {
1850
- if (prev_reaction) updated[prev_reaction] = Math.max(0, (updated[prev_reaction] ?? 0) - 1);
1851
- updated[key] = (updated[key] ?? 0) + 1;
1852
- }
1853
- return updated;
1854
- });
1855
- onReactRef.current?.(next);
1856
- },
1857
- 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"}`,
1858
- "aria-label": key.toLowerCase(),
1859
- "aria-pressed": active,
1860
- children: [
1861
- /* @__PURE__ */ jsx("span", { children: emoji }),
1862
- count > 0 && /* @__PURE__ */ jsx("span", { className: "text-white/70 tabular-nums", children: count })
1863
- ]
1864
- },
1865
- key
1866
- );
1867
- }),
1868
- /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" })
1869
- ] });
1870
- })(),
1871
- /* @__PURE__ */ jsx(
1872
- VolumeSlider,
1873
- {
1874
- volume: isMuted ? 0 : volume,
1875
- onMuteToggle: () => setIsMuted((v) => !v),
1876
- onVolumeChange: (v) => {
1877
- setVolume(v);
1878
- setIsMuted(v === 0);
1879
- },
1880
- isMuted
1881
- }
1882
- ),
1883
- /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
1884
- captions.length > 0 && /* @__PURE__ */ jsx(
1885
- "button",
1886
- {
1887
- type: "button",
1888
- onClick: () => {
1889
- const next = subtitleMode === "off" ? captions[0]?.srclang ?? "off" : "off";
1890
- setSubtitleMode(next);
1891
- setSubtitleStyle((st) => ({ ...st, track: next }));
1892
- },
1893
- className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
1894
- "aria-label": "Captions",
1895
- children: /* @__PURE__ */ jsx(Captions$1, { className: "size-4 @sm:size-5" })
1896
- }
1897
- ),
1898
- /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
1899
- "button",
1900
- {
1901
- type: "button",
1902
- onClick: () => settingsOpen ? closeSettings() : openSettings(),
1903
- className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${settingsOpen ? "text-white" : "text-white/60"}`,
1904
- "aria-label": "Settings",
1905
- children: /* @__PURE__ */ jsx(Settings, { className: "size-4 @sm:size-5" })
1906
- }
1907
- ) }),
1908
- /* @__PURE__ */ jsx(
1909
- "button",
1910
- {
1911
- type: "button",
1912
- onClick: toggleFullscreen,
1913
- className: "grid size-8 place-items-center text-white/60 transition hover:scale-110 hover:text-white/80 @sm:size-10",
1914
- "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
1915
- children: isFullscreen ? /* @__PURE__ */ jsx(Minimize, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Maximize, { className: "size-4 @sm:size-5" })
1916
- }
1917
- )
1918
- ] })
1982
+ }),
1983
+ /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" })
1984
+ ] });
1985
+ })(),
1986
+ /* @__PURE__ */ jsx(
1987
+ VolumeSlider,
1988
+ {
1989
+ volume: isMuted ? 0 : volume,
1990
+ onMuteToggle: () => setIsMuted((v) => !v),
1991
+ onVolumeChange: (v) => {
1992
+ setVolume(v);
1993
+ setIsMuted(v === 0);
1994
+ },
1995
+ isMuted
1996
+ }
1997
+ ),
1998
+ /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
1999
+ captions.length > 0 && /* @__PURE__ */ jsx(
2000
+ "button",
2001
+ {
2002
+ type: "button",
2003
+ onClick: () => {
2004
+ const next = subtitleMode === "off" ? captions[0]?.srclang ?? "off" : "off";
2005
+ setSubtitleMode(next);
2006
+ setSubtitleStyle((st) => ({ ...st, track: next }));
2007
+ },
2008
+ className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
2009
+ "aria-label": "Captions",
2010
+ children: /* @__PURE__ */ jsx(Captions$1, { className: "size-4 @sm:size-5" })
2011
+ }
2012
+ ),
2013
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
2014
+ "button",
2015
+ {
2016
+ type: "button",
2017
+ onClick: () => settingsOpen ? closeSettings() : openSettings(),
2018
+ className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10 ${settingsOpen ? "text-white" : "text-white/60"}`,
2019
+ "aria-label": "Settings",
2020
+ children: /* @__PURE__ */ jsx(Settings, { className: "size-4 @sm:size-5" })
2021
+ }
2022
+ ) }),
2023
+ /* @__PURE__ */ jsx(
2024
+ "button",
2025
+ {
2026
+ type: "button",
2027
+ onClick: toggleFullscreen,
2028
+ className: "grid size-8 place-items-center text-white/60 transition hover:scale-110 hover:text-white/80 @sm:size-10",
2029
+ "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
2030
+ children: isFullscreen ? /* @__PURE__ */ jsx(Minimize, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Maximize, { className: "size-4 @sm:size-5" })
2031
+ }
2032
+ )
1919
2033
  ] })
1920
- ]
1921
- }
1922
- )
1923
- ]
1924
- }
1925
- ),
1926
- activeCue && /* @__PURE__ */ jsx(
1927
- "div",
1928
- {
1929
- 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"}`,
1930
- children: /* @__PURE__ */ jsx(
1931
- "div",
1932
- {
1933
- className: "max-w-[80%] rounded-lg px-4 py-1.5 text-center font-medium leading-snug",
1934
- style: {
1935
- fontSize: (() => {
1936
- const base = Math.max(12, Math.min(playerHeight * 0.028, 32));
1937
- if (subtitleStyle.size === "small") return `${base * 0.75}px`;
1938
- if (subtitleStyle.size === "large") return `${base * 1.35}px`;
1939
- if (subtitleStyle.size === "xlarge") return `${base * 1.8}px`;
1940
- return `${base}px`;
1941
- })(),
1942
- color: subtitleStyle.color === "yellow" ? "#facc15" : subtitleStyle.color === "cyan" ? "#22d3ee" : "#ffffff",
1943
- backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.55)",
1944
- backdropFilter: subtitleStyle.bg === "semi" ? "blur(6px)" : void 0,
1945
- 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)"
1946
- },
1947
- children: activeCue
2034
+ ] })
2035
+ ]
1948
2036
  }
1949
2037
  )
1950
- }
1951
- )
1952
- ]
1953
- }
1954
- )
1955
- ]
2038
+ ]
2039
+ }
2040
+ ),
2041
+ activeCue && /* @__PURE__ */ jsx(
2042
+ "div",
2043
+ {
2044
+ 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"}`,
2045
+ children: /* @__PURE__ */ jsx(
2046
+ "div",
2047
+ {
2048
+ className: "max-w-[80%] rounded-lg px-4 py-1.5 text-center font-medium leading-snug",
2049
+ style: {
2050
+ fontSize: (() => {
2051
+ const base = Math.max(12, Math.min(playerHeight * 0.028, 32));
2052
+ if (subtitleStyle.size === "small") return `${base * 0.75}px`;
2053
+ if (subtitleStyle.size === "large") return `${base * 1.35}px`;
2054
+ if (subtitleStyle.size === "xlarge") return `${base * 1.8}px`;
2055
+ return `${base}px`;
2056
+ })(),
2057
+ color: subtitleStyle.color === "yellow" ? "#facc15" : subtitleStyle.color === "cyan" ? "#22d3ee" : "#ffffff",
2058
+ backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.55)",
2059
+ backdropFilter: subtitleStyle.bg === "semi" ? "blur(6px)" : void 0,
2060
+ 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)"
2061
+ },
2062
+ children: activeCue
2063
+ }
2064
+ )
2065
+ }
2066
+ )
2067
+ ]
2068
+ }
2069
+ )
1956
2070
  }
1957
2071
  );
1958
2072
  }
@@ -1966,6 +2080,9 @@ function VolumeSlider({
1966
2080
  const [hovered, setHovered] = useState(false);
1967
2081
  const [dragging, setDragging] = useState(false);
1968
2082
  const trackRef = useRef(null);
2083
+ const sliderWrapRef = useRef(null);
2084
+ const railRef = useRef(null);
2085
+ const thumbRef = useRef(null);
1969
2086
  const expanded = hovered || dragging;
1970
2087
  const seek = useCallback((clientX) => {
1971
2088
  const track = trackRef.current;
@@ -1983,6 +2100,31 @@ function VolumeSlider({
1983
2100
  if (dragging) seek(e.clientX);
1984
2101
  }, [dragging, seek]);
1985
2102
  const onPointerUp = useCallback(() => setDragging(false), []);
2103
+ useEffect(() => {
2104
+ const wrap = sliderWrapRef.current;
2105
+ if (!wrap) return;
2106
+ gsap.killTweensOf(wrap);
2107
+ gsap.to(wrap, {
2108
+ width: expanded ? 64 : 0,
2109
+ opacity: expanded ? 1 : 0,
2110
+ duration: 0.2,
2111
+ ease: "power2.inOut"
2112
+ });
2113
+ }, [expanded]);
2114
+ useEffect(() => {
2115
+ const rail = railRef.current;
2116
+ const thumb = thumbRef.current;
2117
+ const targetRailH = dragging ? 5 : hovered ? 4 : 3;
2118
+ const targetThumbSize = dragging ? 14 : hovered ? 11 : 0;
2119
+ if (rail) {
2120
+ gsap.killTweensOf(rail);
2121
+ gsap.to(rail, { height: targetRailH, duration: 0.15, ease: "power1.inOut" });
2122
+ }
2123
+ if (thumb) {
2124
+ gsap.killTweensOf(thumb);
2125
+ gsap.to(thumb, { width: targetThumbSize, height: targetThumbSize, duration: 0.15, ease: "power1.inOut" });
2126
+ }
2127
+ }, [dragging, hovered]);
1986
2128
  const fillPercent = volume * 100;
1987
2129
  return /* @__PURE__ */ jsxs(
1988
2130
  "div",
@@ -2006,10 +2148,10 @@ function VolumeSlider({
2006
2148
  /* @__PURE__ */ jsx(
2007
2149
  "div",
2008
2150
  {
2151
+ ref: sliderWrapRef,
2009
2152
  style: {
2010
- width: expanded ? "64px" : "0px",
2011
- opacity: expanded ? 1 : 0,
2012
- transition: "width 0.2s ease, opacity 0.2s ease",
2153
+ width: "0px",
2154
+ opacity: 0,
2013
2155
  overflow: "hidden"
2014
2156
  },
2015
2157
  children: /* @__PURE__ */ jsxs(
@@ -2025,11 +2167,9 @@ function VolumeSlider({
2025
2167
  /* @__PURE__ */ jsx(
2026
2168
  "div",
2027
2169
  {
2170
+ ref: railRef,
2028
2171
  className: "absolute inset-x-0 rounded-full bg-white/20",
2029
- style: {
2030
- height: dragging ? "5px" : hovered ? "4px" : "3px",
2031
- transition: "height 0.15s ease"
2032
- },
2172
+ style: { height: "3px" },
2033
2173
  children: /* @__PURE__ */ jsx(
2034
2174
  "div",
2035
2175
  {
@@ -2042,12 +2182,12 @@ function VolumeSlider({
2042
2182
  /* @__PURE__ */ jsx(
2043
2183
  "div",
2044
2184
  {
2185
+ ref: thumbRef,
2045
2186
  className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white shadow-md",
2046
2187
  style: {
2047
2188
  left: `${fillPercent}%`,
2048
- width: dragging ? "14px" : hovered ? "11px" : "0px",
2049
- height: dragging ? "14px" : hovered ? "11px" : "0px",
2050
- transition: "width 0.15s ease, height 0.15s ease"
2189
+ width: "0px",
2190
+ height: "0px"
2051
2191
  }
2052
2192
  }
2053
2193
  )