@nationaldesignstudio/react 0.5.5 → 0.5.6

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
@@ -1,5 +1,5 @@
1
1
  import { Accordion as Accordion$1 } from '@base-ui-components/react/accordion';
2
- import * as React11 from 'react';
2
+ import * as React14 from 'react';
3
3
  import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
4
4
  import { tv, cnBase } from 'tailwind-variants';
5
5
  export { cnBase as twMerge } from 'tailwind-variants';
@@ -9,8 +9,10 @@ import { useRender } from '@base-ui-components/react/use-render';
9
9
  import { Button as Button$1 } from '@base-ui-components/react/button';
10
10
  import { Popover as Popover$1 } from '@base-ui-components/react/popover';
11
11
  import { Select as Select$1 } from '@base-ui-components/react/select';
12
+ import { ChevronDown, Check, ChevronUp } from 'lucide-react';
12
13
  import { Tooltip as Tooltip$1 } from '@base-ui-components/react/tooltip';
13
- import { Dialog } from '@base-ui-components/react/dialog';
14
+ import { MediaController, MediaLoadingIndicator, MediaControlBar, MediaPlayButton, MediaMuteButton, MediaVolumeRange, MediaTimeDisplay, MediaTimeRange } from 'media-chrome/react';
15
+ import { Dialog as Dialog$1 } from '@base-ui-components/react/dialog';
14
16
  import { Slot } from '@radix-ui/react-slot';
15
17
 
16
18
  // src/components/atoms/accordion/accordion.tsx
@@ -70,10 +72,10 @@ var accordionPanelVariants = tv({
70
72
  colorScheme: "light"
71
73
  }
72
74
  });
73
- var AccordionContext = React11.createContext({
75
+ var AccordionContext = React14.createContext({
74
76
  colorScheme: "light"
75
77
  });
76
- var Accordion = React11.forwardRef(
78
+ var Accordion = React14.forwardRef(
77
79
  ({
78
80
  className,
79
81
  allowMultiple = false,
@@ -81,7 +83,7 @@ var Accordion = React11.forwardRef(
81
83
  colorScheme = "light",
82
84
  children
83
85
  }, ref) => {
84
- const defaultValue = React11.useMemo(() => {
86
+ const defaultValue = React14.useMemo(() => {
85
87
  if (!defaultExpanded) return void 0;
86
88
  if (Array.isArray(defaultExpanded)) return defaultExpanded;
87
89
  return [defaultExpanded];
@@ -99,9 +101,9 @@ var Accordion = React11.forwardRef(
99
101
  }
100
102
  );
101
103
  Accordion.displayName = "Accordion";
102
- var AccordionItem = React11.forwardRef(
104
+ var AccordionItem = React14.forwardRef(
103
105
  ({ className, id, title, children }, ref) => {
104
- const { colorScheme } = React11.useContext(AccordionContext);
106
+ const { colorScheme } = React14.useContext(AccordionContext);
105
107
  return /* @__PURE__ */ jsxs(
106
108
  Accordion$1.Item,
107
109
  {
@@ -148,7 +150,7 @@ AccordionItem.displayName = "AccordionItem";
148
150
  var backgroundVariants = tv({
149
151
  base: "absolute inset-0"
150
152
  });
151
- var Background = React11.forwardRef(
153
+ var Background = React14.forwardRef(
152
154
  ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
153
155
  "div",
154
156
  {
@@ -241,7 +243,7 @@ BackgroundVideo.displayName = "Background.Video";
241
243
  var backgroundStreamVariants = tv({
242
244
  base: "absolute inset-0 size-full border-0 scale-[1.5] object-cover"
243
245
  });
244
- var BackgroundStream = React11.forwardRef(
246
+ var BackgroundStream = React14.forwardRef(
245
247
  ({
246
248
  className,
247
249
  videoId,
@@ -281,7 +283,7 @@ BackgroundStream.displayName = "Background.Stream";
281
283
  var backgroundOverlayVariants = tv({
282
284
  base: "absolute inset-0 bg-bg-overlay"
283
285
  });
284
- var BackgroundOverlay = React11.forwardRef(({ className, opacity = 0.4, style, ...props }, ref) => /* @__PURE__ */ jsx(
286
+ var BackgroundOverlay = React14.forwardRef(({ className, opacity = 0.4, style, ...props }, ref) => /* @__PURE__ */ jsx(
285
287
  "div",
286
288
  {
287
289
  ref,
@@ -298,7 +300,7 @@ BackgroundOverlay.displayName = "Background.Overlay";
298
300
  var backgroundGradientVariants = tv({
299
301
  base: "absolute inset-0"
300
302
  });
301
- var BackgroundGradient = React11.forwardRef(
303
+ var BackgroundGradient = React14.forwardRef(
302
304
  ({
303
305
  className,
304
306
  direction = "to-b",
@@ -334,6 +336,258 @@ var BackgroundCompound = Object.assign(Background, {
334
336
  Overlay: BackgroundOverlay,
335
337
  Gradient: BackgroundGradient
336
338
  });
339
+ var blurredVideoBackdropVariants = tv({
340
+ base: [
341
+ "absolute",
342
+ "pointer-events-none",
343
+ "select-none",
344
+ "will-change-contents",
345
+ "transform-gpu"
346
+ ],
347
+ variants: {
348
+ /**
349
+ * Blur intensity level.
350
+ * Higher values provide more diffused backgrounds.
351
+ */
352
+ blur: {
353
+ low: "",
354
+ medium: "",
355
+ high: "",
356
+ extreme: ""
357
+ },
358
+ /**
359
+ * Gradient overlay for visual depth.
360
+ */
361
+ overlay: {
362
+ none: "",
363
+ vignette: "",
364
+ "top-bottom": ""
365
+ }
366
+ },
367
+ defaultVariants: {
368
+ blur: "high",
369
+ overlay: "none"
370
+ }
371
+ });
372
+ var canvasVariants = tv({
373
+ base: ["w-full", "h-full", "object-cover"]
374
+ });
375
+ var gradientOverlayVariants = tv({
376
+ base: ["absolute", "inset-0", "pointer-events-none"]
377
+ });
378
+ var OVERLAY_GRADIENTS = {
379
+ vignette: "radial-gradient(ellipse at center, transparent 40%, rgba(0, 0, 0, 0.4) 100%)",
380
+ "top-bottom": "linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, transparent 30%, transparent 70%, rgba(0, 0, 0, 0.4) 100%)"
381
+ };
382
+ var BLUR_AMOUNTS = {
383
+ low: 40,
384
+ medium: 80,
385
+ high: 100,
386
+ extreme: 120
387
+ };
388
+ function useCanvasBlur({
389
+ videoRef,
390
+ blurAmount,
391
+ enabled = true,
392
+ targetFps = 30,
393
+ scale = 0.5
394
+ }) {
395
+ const canvasRef = React14.useRef(null);
396
+ const ctxRef = React14.useRef(null);
397
+ const [isRendering, setIsRendering] = React14.useState(false);
398
+ const [metrics, setMetrics] = React14.useState({ fps: 0, frameTime: 0 });
399
+ const [videoReady, setVideoReady] = React14.useState(false);
400
+ const lastFrameTimeRef = React14.useRef(0);
401
+ const frameCountRef = React14.useRef(0);
402
+ const fpsIntervalRef = React14.useRef(0);
403
+ const frameInterval = 1e3 / targetFps;
404
+ React14.useEffect(() => {
405
+ if (!enabled) return;
406
+ const checkRef = () => {
407
+ if (videoRef.current && canvasRef.current) {
408
+ setVideoReady(true);
409
+ }
410
+ };
411
+ checkRef();
412
+ const frameId = requestAnimationFrame(checkRef);
413
+ const timeoutId = setTimeout(checkRef, 100);
414
+ const timeoutId2 = setTimeout(checkRef, 500);
415
+ return () => {
416
+ cancelAnimationFrame(frameId);
417
+ clearTimeout(timeoutId);
418
+ clearTimeout(timeoutId2);
419
+ };
420
+ }, [enabled, videoRef]);
421
+ React14.useEffect(() => {
422
+ if (!enabled || !videoReady) return;
423
+ const video = videoRef.current;
424
+ const canvas = canvasRef.current;
425
+ if (!video || !canvas) return;
426
+ const ctx = canvas.getContext("2d", {
427
+ alpha: false,
428
+ desynchronized: true
429
+ // Reduces latency
430
+ });
431
+ if (!ctx) return;
432
+ ctxRef.current = ctx;
433
+ let animationFrameId;
434
+ let isActive = true;
435
+ const updateCanvasSize = () => {
436
+ if (video.videoWidth && video.videoHeight) {
437
+ canvas.width = Math.floor(video.videoWidth * scale);
438
+ canvas.height = Math.floor(video.videoHeight * scale);
439
+ }
440
+ };
441
+ const render = (timestamp) => {
442
+ if (!isActive || !video || !ctx) return;
443
+ const elapsed = timestamp - lastFrameTimeRef.current;
444
+ if (elapsed >= frameInterval) {
445
+ const frameStart = performance.now();
446
+ if (canvas.width === 0 || canvas.height === 0) {
447
+ updateCanvasSize();
448
+ }
449
+ if (video.readyState >= 2 && !video.paused) {
450
+ ctx.filter = `blur(${blurAmount * scale}px)`;
451
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
452
+ setIsRendering(true);
453
+ }
454
+ const frameTime = performance.now() - frameStart;
455
+ frameCountRef.current++;
456
+ if (timestamp - fpsIntervalRef.current >= 1e3) {
457
+ setMetrics({
458
+ fps: frameCountRef.current,
459
+ frameTime: Math.round(frameTime * 100) / 100
460
+ });
461
+ frameCountRef.current = 0;
462
+ fpsIntervalRef.current = timestamp;
463
+ }
464
+ lastFrameTimeRef.current = timestamp - elapsed % frameInterval;
465
+ }
466
+ animationFrameId = requestAnimationFrame(render);
467
+ };
468
+ const handleLoadedMetadata = () => {
469
+ updateCanvasSize();
470
+ };
471
+ const handlePlay = () => {
472
+ if (isActive) {
473
+ animationFrameId = requestAnimationFrame(render);
474
+ }
475
+ };
476
+ const handlePause = () => {
477
+ setIsRendering(false);
478
+ };
479
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
480
+ video.addEventListener("play", handlePlay);
481
+ video.addEventListener("pause", handlePause);
482
+ if (video.readyState >= 1) {
483
+ updateCanvasSize();
484
+ }
485
+ if (!video.paused) {
486
+ animationFrameId = requestAnimationFrame(render);
487
+ }
488
+ return () => {
489
+ isActive = false;
490
+ cancelAnimationFrame(animationFrameId);
491
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
492
+ video.removeEventListener("play", handlePlay);
493
+ video.removeEventListener("pause", handlePause);
494
+ setIsRendering(false);
495
+ };
496
+ }, [enabled, videoReady, videoRef, blurAmount, frameInterval, scale]);
497
+ return {
498
+ canvasRef,
499
+ isRendering,
500
+ metrics
501
+ };
502
+ }
503
+ var BlurredVideoBackdrop = React14.forwardRef(
504
+ ({
505
+ className,
506
+ videoRef,
507
+ blur = "high",
508
+ overlay = "none",
509
+ opacity = 0.6,
510
+ extension = 120,
511
+ targetFps = 30,
512
+ scale = 0.5,
513
+ showMetrics = false,
514
+ style,
515
+ ...props
516
+ }, ref) => {
517
+ const blurAmount = BLUR_AMOUNTS[blur ?? "high"];
518
+ const { canvasRef, isRendering, metrics } = useCanvasBlur({
519
+ videoRef,
520
+ blurAmount,
521
+ enabled: true,
522
+ targetFps,
523
+ scale
524
+ });
525
+ return /* @__PURE__ */ jsxs(
526
+ "div",
527
+ {
528
+ ref,
529
+ className: cn(
530
+ blurredVideoBackdropVariants({ blur, overlay }),
531
+ className
532
+ ),
533
+ style: {
534
+ inset: `-${extension}px`,
535
+ opacity,
536
+ contain: "layout style paint",
537
+ ...style
538
+ },
539
+ "data-blur": blur ?? "high",
540
+ "data-overlay": overlay ?? "none",
541
+ "data-rendering": isRendering,
542
+ "aria-hidden": "true",
543
+ ...props,
544
+ children: [
545
+ /* @__PURE__ */ jsx(
546
+ "canvas",
547
+ {
548
+ ref: canvasRef,
549
+ className: cn(
550
+ canvasVariants(),
551
+ // Scale up the low-res canvas to fill container
552
+ "scale-[2]",
553
+ // Inverse of 0.5 scale factor
554
+ "origin-center"
555
+ ),
556
+ style: {
557
+ // Additional CSS blur for smoother appearance
558
+ filter: `blur(${blurAmount * 0.3}px)`
559
+ }
560
+ }
561
+ ),
562
+ overlay && overlay !== "none" && /* @__PURE__ */ jsx(
563
+ "div",
564
+ {
565
+ className: gradientOverlayVariants(),
566
+ style: { background: OVERLAY_GRADIENTS[overlay] }
567
+ }
568
+ ),
569
+ showMetrics && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-8 left-8 z-10 bg-black/80 text-white typography-caption px-8 py-4 rounded-4 font-mono", children: [
570
+ /* @__PURE__ */ jsxs("div", { children: [
571
+ "FPS: ",
572
+ metrics.fps
573
+ ] }),
574
+ /* @__PURE__ */ jsxs("div", { children: [
575
+ "Frame: ",
576
+ metrics.frameTime,
577
+ "ms"
578
+ ] }),
579
+ /* @__PURE__ */ jsxs("div", { children: [
580
+ "Scale: ",
581
+ scale,
582
+ "x"
583
+ ] })
584
+ ] })
585
+ ]
586
+ }
587
+ );
588
+ }
589
+ );
590
+ BlurredVideoBackdrop.displayName = "BlurredVideoBackdrop";
337
591
 
338
592
  // src/lib/theme.ts
339
593
  var FONT_SIZES = [
@@ -553,7 +807,7 @@ function hasThemeValues(theme) {
553
807
  if (!theme) return false;
554
808
  return Object.values(theme).some((v) => v !== void 0 && v !== null);
555
809
  }
556
- var Button = React11.forwardRef(
810
+ var Button = React14.forwardRef(
557
811
  ({ className, variant, size, render, nativeButton, theme, style, ...props }, ref) => {
558
812
  const isNativeButton = nativeButton ?? render === void 0;
559
813
  const hasTheme = hasThemeValues(theme);
@@ -583,7 +837,7 @@ var Button = React11.forwardRef(
583
837
  );
584
838
  Button.displayName = "Button";
585
839
  var iconButtonVariants = tv({
586
- base: "inline-flex items-center justify-center whitespace-nowrap transition-colors duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
840
+ base: "inline-flex items-center justify-center whitespace-nowrap transition-colors duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&>svg]:shrink-0",
587
841
  variants: {
588
842
  variant: {
589
843
  // Primary - filled brand button
@@ -600,15 +854,21 @@ var iconButtonVariants = tv({
600
854
  "ghost-inverse": "bg-button-ghost-inverse-bg text-button-ghost-inverse-text hover:bg-button-ghost-inverse-bg-hover hover:text-button-ghost-inverse-text-hover border-transparent focus-visible:ring-gray-50 focus-visible:ring-offset-gray-1000"
601
855
  },
602
856
  size: {
603
- sm: "size-28 rounded-surface-button-small",
604
- md: "size-40 rounded-surface-button-medium",
605
- lg: "size-56 rounded-surface-button-large"
857
+ sm: "size-28",
858
+ md: "size-40",
859
+ lg: "size-56"
606
860
  },
607
861
  rounded: {
608
862
  default: "",
609
863
  full: "rounded-full"
610
864
  }
611
865
  },
866
+ compoundVariants: [
867
+ // Apply size-specific rounded only when rounded is "default"
868
+ { size: "sm", rounded: "default", class: "rounded-surface-button-small" },
869
+ { size: "md", rounded: "default", class: "rounded-surface-button-medium" },
870
+ { size: "lg", rounded: "default", class: "rounded-surface-button-large" }
871
+ ],
612
872
  defaultVariants: {
613
873
  variant: "primary",
614
874
  size: "md",
@@ -707,7 +967,7 @@ var inputVariants = tv({
707
967
  error: false
708
968
  }
709
969
  });
710
- var Input = React11.forwardRef(
970
+ var Input = React14.forwardRef(
711
971
  ({ className, size, error, type = "text", ...props }, ref) => {
712
972
  return /* @__PURE__ */ jsx(
713
973
  "input",
@@ -937,7 +1197,7 @@ function InputGroupTextarea({ className, ...props }) {
937
1197
  }
938
1198
  );
939
1199
  }
940
- var NdstudioFooter = React11.forwardRef(
1200
+ var NdstudioFooter = React14.forwardRef(
941
1201
  ({ className, href = "https://ndstudio.gov", ...props }, ref) => {
942
1202
  return /* @__PURE__ */ jsx("div", { ref, className: cn("text-center", className), ...props, children: /* @__PURE__ */ jsxs("p", { className: "typography-label-large uppercase text-ivory-alpha-75", children: [
943
1203
  "Designed and Engineered in DC by",
@@ -992,7 +1252,7 @@ var dotBaseVariants = tv({
992
1252
  variant: "charcoal"
993
1253
  }
994
1254
  });
995
- var PagerControl = React11.forwardRef(
1255
+ var PagerControl = React14.forwardRef(
996
1256
  ({
997
1257
  className,
998
1258
  size,
@@ -1006,12 +1266,12 @@ var PagerControl = React11.forwardRef(
1006
1266
  loop = true,
1007
1267
  ...props
1008
1268
  }, ref) => {
1009
- const [internalIndex, setInternalIndex] = React11.useState(0);
1010
- const [isPaused, setIsPaused] = React11.useState(false);
1011
- const [progress, setProgress] = React11.useState(0);
1269
+ const [internalIndex, setInternalIndex] = React14.useState(0);
1270
+ const [isPaused, setIsPaused] = React14.useState(false);
1271
+ const [progress, setProgress] = React14.useState(0);
1012
1272
  const activeIndex = controlledIndex !== void 0 ? controlledIndex : internalIndex;
1013
1273
  const isControlled = controlledIndex !== void 0;
1014
- React11.useEffect(() => {
1274
+ React14.useEffect(() => {
1015
1275
  if (import.meta.env?.DEV) {
1016
1276
  if (count < 1) {
1017
1277
  console.warn("PagerControl: count must be at least 1");
@@ -1034,10 +1294,10 @@ var PagerControl = React11.forwardRef(
1034
1294
  }
1035
1295
  }, [count, controlledIndex, isControlled, onChange]);
1036
1296
  const safeActiveIndex = Math.max(0, Math.min(activeIndex, count - 1));
1037
- const animationFrameRef = React11.useRef(null);
1038
- const startTimeRef = React11.useRef(null);
1039
- const pausedProgressRef = React11.useRef(0);
1040
- const goToNext = React11.useCallback(() => {
1297
+ const animationFrameRef = React14.useRef(null);
1298
+ const startTimeRef = React14.useRef(null);
1299
+ const pausedProgressRef = React14.useRef(0);
1300
+ const goToNext = React14.useCallback(() => {
1041
1301
  const nextIndex = safeActiveIndex + 1;
1042
1302
  if (nextIndex >= count) {
1043
1303
  if (loop) {
@@ -1049,7 +1309,7 @@ var PagerControl = React11.forwardRef(
1049
1309
  onChange?.(nextIndex);
1050
1310
  }
1051
1311
  }, [safeActiveIndex, count, loop, isControlled, onChange]);
1052
- const goToIndex = React11.useCallback(
1312
+ const goToIndex = React14.useCallback(
1053
1313
  (index) => {
1054
1314
  if (!isControlled) setInternalIndex(index);
1055
1315
  onChange?.(index);
@@ -1059,7 +1319,7 @@ var PagerControl = React11.forwardRef(
1059
1319
  },
1060
1320
  [isControlled, onChange]
1061
1321
  );
1062
- React11.useEffect(() => {
1322
+ React14.useEffect(() => {
1063
1323
  if (!autoPlay || duration2 <= 0 || isPaused) {
1064
1324
  if (animationFrameRef.current) {
1065
1325
  cancelAnimationFrame(animationFrameRef.current);
@@ -1090,19 +1350,19 @@ var PagerControl = React11.forwardRef(
1090
1350
  }
1091
1351
  };
1092
1352
  }, [autoPlay, duration2, isPaused, goToNext]);
1093
- const handleMouseEnter = React11.useCallback(() => {
1353
+ const handleMouseEnter = React14.useCallback(() => {
1094
1354
  if (pauseOnHover) {
1095
1355
  pausedProgressRef.current = progress;
1096
1356
  startTimeRef.current = null;
1097
1357
  setIsPaused(true);
1098
1358
  }
1099
1359
  }, [pauseOnHover, progress]);
1100
- const handleMouseLeave = React11.useCallback(() => {
1360
+ const handleMouseLeave = React14.useCallback(() => {
1101
1361
  if (pauseOnHover) {
1102
1362
  setIsPaused(false);
1103
1363
  }
1104
1364
  }, [pauseOnHover]);
1105
- React11.useEffect(() => {
1365
+ React14.useEffect(() => {
1106
1366
  if (isControlled) {
1107
1367
  setProgress(0);
1108
1368
  pausedProgressRef.current = 0;
@@ -1297,9 +1557,9 @@ var popoverArrowVariants = floatingArrowVariants;
1297
1557
  var PopoverRoot = ({ children, ...props }) => {
1298
1558
  return /* @__PURE__ */ jsx(Popover$1.Root, { ...props, children });
1299
1559
  };
1300
- var PopoverTrigger = React11.forwardRef(
1560
+ var PopoverTrigger = React14.forwardRef(
1301
1561
  ({ className, children, ...props }, ref) => {
1302
- const isSingleElement = React11.isValidElement(children);
1562
+ const isSingleElement = React14.isValidElement(children);
1303
1563
  if (isSingleElement) {
1304
1564
  return /* @__PURE__ */ jsx(
1305
1565
  Popover$1.Trigger,
@@ -1318,7 +1578,7 @@ PopoverTrigger.displayName = "PopoverTrigger";
1318
1578
  var PopoverPortal = ({ children, ...props }) => {
1319
1579
  return /* @__PURE__ */ jsx(Popover$1.Portal, { ...props, children });
1320
1580
  };
1321
- var PopoverBackdrop = React11.forwardRef(
1581
+ var PopoverBackdrop = React14.forwardRef(
1322
1582
  ({ className, ...props }, ref) => {
1323
1583
  return /* @__PURE__ */ jsx(
1324
1584
  Popover$1.Backdrop,
@@ -1331,7 +1591,7 @@ var PopoverBackdrop = React11.forwardRef(
1331
1591
  }
1332
1592
  );
1333
1593
  PopoverBackdrop.displayName = "PopoverBackdrop";
1334
- var PopoverPositioner = React11.forwardRef(({ className, side = "bottom", sideOffset = 8, ...props }, ref) => {
1594
+ var PopoverPositioner = React14.forwardRef(({ className, side = "bottom", sideOffset = 8, ...props }, ref) => {
1335
1595
  return /* @__PURE__ */ jsx(
1336
1596
  Popover$1.Positioner,
1337
1597
  {
@@ -1344,7 +1604,7 @@ var PopoverPositioner = React11.forwardRef(({ className, side = "bottom", sideOf
1344
1604
  );
1345
1605
  });
1346
1606
  PopoverPositioner.displayName = "PopoverPositioner";
1347
- var PopoverPopup = React11.forwardRef(
1607
+ var PopoverPopup = React14.forwardRef(
1348
1608
  ({ className, variant, ...props }, ref) => {
1349
1609
  return /* @__PURE__ */ jsx(
1350
1610
  Popover$1.Popup,
@@ -1357,7 +1617,7 @@ var PopoverPopup = React11.forwardRef(
1357
1617
  }
1358
1618
  );
1359
1619
  PopoverPopup.displayName = "PopoverPopup";
1360
- var PopoverArrow = React11.forwardRef(
1620
+ var PopoverArrow = React14.forwardRef(
1361
1621
  ({ className, ...props }, ref) => {
1362
1622
  return /* @__PURE__ */ jsx(
1363
1623
  Popover$1.Arrow,
@@ -1377,7 +1637,7 @@ var PopoverArrow = React11.forwardRef(
1377
1637
  }
1378
1638
  );
1379
1639
  PopoverArrow.displayName = "PopoverArrow";
1380
- var PopoverTitle = React11.forwardRef(
1640
+ var PopoverTitle = React14.forwardRef(
1381
1641
  ({ className, ...props }, ref) => {
1382
1642
  return /* @__PURE__ */ jsx(
1383
1643
  Popover$1.Title,
@@ -1390,7 +1650,7 @@ var PopoverTitle = React11.forwardRef(
1390
1650
  }
1391
1651
  );
1392
1652
  PopoverTitle.displayName = "PopoverTitle";
1393
- var PopoverDescription = React11.forwardRef(({ className, ...props }, ref) => {
1653
+ var PopoverDescription = React14.forwardRef(({ className, ...props }, ref) => {
1394
1654
  return /* @__PURE__ */ jsx(
1395
1655
  Popover$1.Description,
1396
1656
  {
@@ -1404,7 +1664,7 @@ var PopoverDescription = React11.forwardRef(({ className, ...props }, ref) => {
1404
1664
  );
1405
1665
  });
1406
1666
  PopoverDescription.displayName = "PopoverDescription";
1407
- var PopoverClose = React11.forwardRef(
1667
+ var PopoverClose = React14.forwardRef(
1408
1668
  ({ className, ...props }, ref) => {
1409
1669
  return /* @__PURE__ */ jsx(
1410
1670
  Popover$1.Close,
@@ -1495,7 +1755,9 @@ var selectTriggerVariants = tv({
1495
1755
  // Override disabled to use data attribute (Base UI pattern)
1496
1756
  "data-[disabled]:bg-ui-control-background-disabled data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
1497
1757
  // Open state styling
1498
- "data-[popup-open]:border-ui-accent-base data-[popup-open]:ring-4 data-[popup-open]:ring-ui-color-focus data-[popup-open]:bg-ui-control-background"
1758
+ "data-[popup-open]:border-ui-accent-base data-[popup-open]:ring-4 data-[popup-open]:ring-ui-color-focus data-[popup-open]:bg-ui-control-background",
1759
+ // Invalid state (aria-invalid)
1760
+ "aria-[invalid=true]:border-ui-error-color aria-[invalid=true]:ring-ui-error-color/20"
1499
1761
  ],
1500
1762
  variants: {
1501
1763
  size: formControlSizes,
@@ -1509,19 +1771,25 @@ var selectTriggerVariants = tv({
1509
1771
  var selectPopupVariants = tv({
1510
1772
  base: [
1511
1773
  // Layout - match trigger width using CSS custom property from Base UI
1512
- "flex flex-col gap-2 p-10",
1774
+ "flex flex-col gap-2 p-8",
1513
1775
  "w-[var(--anchor-width)]",
1514
- // Background and border - uses surface ui radius for theming support
1515
- "bg-ui-control-background border border-solid border-ui-color-border-active rounded-surface-ui-medium",
1516
- // Focus ring shadow (ui-focus-state from Figma)
1517
- "ring-4 ring-ui-color-focus",
1776
+ // Background - uses overlay token
1777
+ "bg-overlay-background",
1778
+ // Border - uses overlay token for subtle border
1779
+ "border border-overlay-border",
1780
+ // Border radius - uses overlay token for consistency with other overlays
1781
+ "rounded-surface-overlay",
1782
+ // Shadow for elevation
1783
+ "shadow-lg",
1518
1784
  // Animation
1519
1785
  "origin-[var(--transform-origin)]",
1520
1786
  "transition-[transform,scale,opacity] duration-150",
1521
1787
  "data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
1522
1788
  "data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
1523
1789
  // Ensure it's above other content
1524
- "z-50"
1790
+ "z-50",
1791
+ // Scrollable support
1792
+ "overflow-y-auto max-h-[var(--available-height,300px)]"
1525
1793
  ]
1526
1794
  });
1527
1795
  var selectOptionVariants = tv({
@@ -1546,84 +1814,86 @@ var selectOptionVariants = tv({
1546
1814
  "data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"
1547
1815
  ]
1548
1816
  });
1549
- var SelectChevronIcon = ({ className }) => /* @__PURE__ */ jsx(
1550
- "svg",
1551
- {
1552
- className: cn("size-16 text-gray-500 shrink-0", className),
1553
- viewBox: "0 0 16 16",
1554
- fill: "none",
1555
- xmlns: "http://www.w3.org/2000/svg",
1556
- "aria-hidden": "true",
1557
- children: /* @__PURE__ */ jsx(
1558
- "path",
1559
- {
1560
- d: "M4 6L8 10L12 6",
1561
- stroke: "currentColor",
1562
- strokeWidth: "1.5",
1563
- strokeLinecap: "round",
1564
- strokeLinejoin: "round"
1565
- }
1566
- )
1567
- }
1568
- );
1569
- var CheckIcon = ({ className }) => /* @__PURE__ */ jsx(
1570
- "svg",
1571
- {
1572
- className: cn("size-14 shrink-0", className),
1573
- viewBox: "0 0 14 14",
1574
- fill: "none",
1575
- xmlns: "http://www.w3.org/2000/svg",
1576
- "aria-hidden": "true",
1577
- children: /* @__PURE__ */ jsx(
1578
- "path",
1579
- {
1580
- d: "M11.6666 3.5L5.24992 9.91667L2.33325 7",
1581
- stroke: "currentColor",
1582
- strokeWidth: "1.5",
1583
- strokeLinecap: "round",
1584
- strokeLinejoin: "round"
1585
- }
1586
- )
1587
- }
1588
- );
1817
+ var selectSeparatorVariants = tv({
1818
+ base: ["h-px my-6 -mx-8", "bg-overlay-border"]
1819
+ });
1820
+ var selectScrollArrowVariants = tv({
1821
+ base: [
1822
+ "flex items-center justify-center",
1823
+ "py-4",
1824
+ "text-text-muted",
1825
+ "cursor-default",
1826
+ // Sticky positioning for scroll indicators
1827
+ "data-[direction=up]:sticky data-[direction=up]:top-0",
1828
+ "data-[direction=down]:sticky data-[direction=down]:bottom-0",
1829
+ "bg-overlay-background"
1830
+ ]
1831
+ });
1589
1832
  var SelectRoot = ({
1590
1833
  children,
1591
1834
  ...props
1592
1835
  }) => {
1593
1836
  return /* @__PURE__ */ jsx(Select$1.Root, { ...props, children });
1594
1837
  };
1595
- var SelectTrigger = React11.forwardRef(
1596
- ({ className, size, error, placeholder = "Select option...", ...props }, ref) => {
1838
+ var SelectTrigger = React14.forwardRef(
1839
+ ({
1840
+ className,
1841
+ size,
1842
+ error,
1843
+ placeholder = "Select option...",
1844
+ "aria-label": ariaLabel,
1845
+ ...props
1846
+ }, ref) => {
1597
1847
  return /* @__PURE__ */ jsxs(
1598
1848
  Select$1.Trigger,
1599
1849
  {
1600
1850
  ref,
1851
+ "aria-label": ariaLabel ?? placeholder,
1852
+ "aria-invalid": error || void 0,
1601
1853
  className: cn(selectTriggerVariants({ size, error }), className),
1854
+ "data-size": size ?? "default",
1855
+ "data-error": error ?? false,
1602
1856
  ...props,
1603
1857
  children: [
1604
1858
  /* @__PURE__ */ jsx(Select$1.Value, { children: (value) => value ? value : /* @__PURE__ */ jsx("span", { className: "text-text-muted", children: placeholder }) }),
1605
- /* @__PURE__ */ jsx(Select$1.Icon, { children: /* @__PURE__ */ jsx(SelectChevronIcon, {}) })
1859
+ /* @__PURE__ */ jsx(Select$1.Icon, { "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-16 text-gray-500 shrink-0" }) })
1606
1860
  ]
1607
1861
  }
1608
1862
  );
1609
1863
  }
1610
1864
  );
1611
1865
  SelectTrigger.displayName = "SelectTrigger";
1612
- var SelectPopup = React11.forwardRef(
1613
- ({ className, children, ...props }, ref) => {
1614
- return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Positioner, { side: "bottom", sideOffset: 4, align: "start", children: /* @__PURE__ */ jsx(
1615
- Select$1.Popup,
1866
+ var SelectValue = React14.forwardRef(
1867
+ ({ className, placeholder = "Select option...", ...props }, ref) => {
1868
+ return /* @__PURE__ */ jsx(Select$1.Value, { ref, className, ...props, children: (value) => value ? value : /* @__PURE__ */ jsx("span", { className: "text-text-muted", children: placeholder }) });
1869
+ }
1870
+ );
1871
+ SelectValue.displayName = "SelectValue";
1872
+ var SelectPopup = React14.forwardRef(
1873
+ ({ className, children, alignItemWithTrigger = true, ...props }, ref) => {
1874
+ return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(
1875
+ Select$1.Positioner,
1616
1876
  {
1617
- ref,
1618
- className: cn(selectPopupVariants(), className),
1619
- ...props,
1620
- children
1877
+ side: "bottom",
1878
+ sideOffset: 4,
1879
+ align: "start",
1880
+ alignItemWithTrigger,
1881
+ children: /* @__PURE__ */ jsx(
1882
+ Select$1.Popup,
1883
+ {
1884
+ ref,
1885
+ className: cn(selectPopupVariants(), className),
1886
+ ...props,
1887
+ children
1888
+ }
1889
+ )
1621
1890
  }
1622
- ) }) });
1891
+ ) });
1623
1892
  }
1624
1893
  );
1625
1894
  SelectPopup.displayName = "SelectPopup";
1626
- var SelectOption = React11.forwardRef(
1895
+ var SelectContent = SelectPopup;
1896
+ var SelectOption = React14.forwardRef(
1627
1897
  ({ className, children, ...props }, ref) => {
1628
1898
  return /* @__PURE__ */ jsxs(
1629
1899
  Select$1.Item,
@@ -1633,20 +1903,21 @@ var SelectOption = React11.forwardRef(
1633
1903
  ...props,
1634
1904
  children: [
1635
1905
  /* @__PURE__ */ jsx(Select$1.ItemText, { children }),
1636
- /* @__PURE__ */ jsx(Select$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) })
1906
+ /* @__PURE__ */ jsx(Select$1.ItemIndicator, { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Check, { className: "size-14 shrink-0" }) })
1637
1907
  ]
1638
1908
  }
1639
1909
  );
1640
1910
  }
1641
1911
  );
1642
1912
  SelectOption.displayName = "SelectOption";
1643
- var SelectGroup = React11.forwardRef(
1913
+ var SelectItem = SelectOption;
1914
+ var SelectGroup = React14.forwardRef(
1644
1915
  ({ className, children, ...props }, ref) => {
1645
1916
  return /* @__PURE__ */ jsx(Select$1.Group, { ref, className, ...props, children });
1646
1917
  }
1647
1918
  );
1648
1919
  SelectGroup.displayName = "SelectGroup";
1649
- var SelectGroupLabel = React11.forwardRef(({ className, children, ...props }, ref) => {
1920
+ var SelectGroupLabel = React14.forwardRef(({ className, children, ...props }, ref) => {
1650
1921
  return /* @__PURE__ */ jsx(
1651
1922
  Select$1.GroupLabel,
1652
1923
  {
@@ -1661,12 +1932,61 @@ var SelectGroupLabel = React11.forwardRef(({ className, children, ...props }, re
1661
1932
  );
1662
1933
  });
1663
1934
  SelectGroupLabel.displayName = "SelectGroupLabel";
1935
+ var SelectLabel = SelectGroupLabel;
1936
+ var SelectSeparator = React14.forwardRef(
1937
+ ({ className, ...props }, ref) => {
1938
+ return /* @__PURE__ */ jsx(
1939
+ Select$1.Separator,
1940
+ {
1941
+ ref,
1942
+ className: cn(selectSeparatorVariants(), className),
1943
+ ...props
1944
+ }
1945
+ );
1946
+ }
1947
+ );
1948
+ SelectSeparator.displayName = "SelectSeparator";
1949
+ var SelectScrollUpArrow = React14.forwardRef(({ className, ...props }, ref) => {
1950
+ return /* @__PURE__ */ jsx(
1951
+ Select$1.ScrollUpArrow,
1952
+ {
1953
+ ref,
1954
+ "data-direction": "up",
1955
+ "aria-label": "Scroll up",
1956
+ className: cn(selectScrollArrowVariants(), className),
1957
+ ...props,
1958
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-12", "aria-hidden": "true" })
1959
+ }
1960
+ );
1961
+ });
1962
+ SelectScrollUpArrow.displayName = "SelectScrollUpArrow";
1963
+ var SelectScrollDownArrow = React14.forwardRef(({ className, ...props }, ref) => {
1964
+ return /* @__PURE__ */ jsx(
1965
+ Select$1.ScrollDownArrow,
1966
+ {
1967
+ ref,
1968
+ "data-direction": "down",
1969
+ "aria-label": "Scroll down",
1970
+ className: cn(selectScrollArrowVariants(), className),
1971
+ ...props,
1972
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-12", "aria-hidden": "true" })
1973
+ }
1974
+ );
1975
+ });
1976
+ SelectScrollDownArrow.displayName = "SelectScrollDownArrow";
1664
1977
  var Select = Object.assign(SelectRoot, {
1665
1978
  Trigger: SelectTrigger,
1979
+ Value: SelectValue,
1666
1980
  Popup: SelectPopup,
1981
+ Content: SelectContent,
1667
1982
  Option: SelectOption,
1983
+ Item: SelectItem,
1668
1984
  Group: SelectGroup,
1669
- GroupLabel: SelectGroupLabel
1985
+ GroupLabel: SelectGroupLabel,
1986
+ Label: SelectLabel,
1987
+ Separator: SelectSeparator,
1988
+ ScrollUpArrow: SelectScrollUpArrow,
1989
+ ScrollDownArrow: SelectScrollDownArrow
1670
1990
  });
1671
1991
  var tooltipPopupVariants = tv({
1672
1992
  base: [
@@ -1707,9 +2027,9 @@ var TooltipProvider = ({ children, ...props }) => {
1707
2027
  var TooltipRoot = ({ children, ...props }) => {
1708
2028
  return /* @__PURE__ */ jsx(Tooltip$1.Root, { ...props, children });
1709
2029
  };
1710
- var TooltipTrigger = React11.forwardRef(
2030
+ var TooltipTrigger = React14.forwardRef(
1711
2031
  ({ className, children, ...props }, ref) => {
1712
- const isSingleElement = React11.isValidElement(children);
2032
+ const isSingleElement = React14.isValidElement(children);
1713
2033
  if (isSingleElement) {
1714
2034
  return /* @__PURE__ */ jsx(
1715
2035
  Tooltip$1.Trigger,
@@ -1728,7 +2048,7 @@ TooltipTrigger.displayName = "TooltipTrigger";
1728
2048
  var TooltipPortal = ({ children, ...props }) => {
1729
2049
  return /* @__PURE__ */ jsx(Tooltip$1.Portal, { ...props, children });
1730
2050
  };
1731
- var TooltipPositioner = React11.forwardRef(({ className, side = "top", sideOffset = 8, ...props }, ref) => {
2051
+ var TooltipPositioner = React14.forwardRef(({ className, side = "top", sideOffset = 8, ...props }, ref) => {
1732
2052
  return /* @__PURE__ */ jsx(
1733
2053
  Tooltip$1.Positioner,
1734
2054
  {
@@ -1741,7 +2061,7 @@ var TooltipPositioner = React11.forwardRef(({ className, side = "top", sideOffse
1741
2061
  );
1742
2062
  });
1743
2063
  TooltipPositioner.displayName = "TooltipPositioner";
1744
- var TooltipPopup = React11.forwardRef(
2064
+ var TooltipPopup = React14.forwardRef(
1745
2065
  ({ className, variant, ...props }, ref) => {
1746
2066
  return /* @__PURE__ */ jsx(
1747
2067
  Tooltip$1.Popup,
@@ -1755,7 +2075,7 @@ var TooltipPopup = React11.forwardRef(
1755
2075
  }
1756
2076
  );
1757
2077
  TooltipPopup.displayName = "TooltipPopup";
1758
- var TooltipArrow = React11.forwardRef(
2078
+ var TooltipArrow = React14.forwardRef(
1759
2079
  ({ className, ...props }, ref) => {
1760
2080
  return /* @__PURE__ */ jsx(
1761
2081
  Tooltip$1.Arrow,
@@ -1808,6 +2128,870 @@ var TooltipParts = Object.assign(TooltipRoot, {
1808
2128
  Popup: TooltipPopup,
1809
2129
  Arrow: TooltipArrow
1810
2130
  });
2131
+ var captionOverlayVariants = tv({
2132
+ base: [
2133
+ // Positioning - absolute at bottom of video container
2134
+ "pointer-events-none",
2135
+ "absolute right-0 left-0",
2136
+ "z-10",
2137
+ "flex justify-center",
2138
+ "px-4"
2139
+ ],
2140
+ variants: {
2141
+ position: {
2142
+ bottom: "bottom-64",
2143
+ "bottom-sm": "bottom-24"
2144
+ }
2145
+ },
2146
+ defaultVariants: {
2147
+ position: "bottom-sm"
2148
+ }
2149
+ });
2150
+ var captionTextVariants = tv({
2151
+ base: [
2152
+ "flex items-center justify-center",
2153
+ "w-fit max-w-[80%]",
2154
+ "gap-10",
2155
+ "px-12 py-6",
2156
+ "text-center",
2157
+ "font-normal leading-[1.4]",
2158
+ "rounded-6",
2159
+ "bg-video-player-caption-bg text-video-player-caption-text"
2160
+ ],
2161
+ variants: {
2162
+ size: {
2163
+ sm: "text-14",
2164
+ md: "[font-size:clamp(16px,2vw,24px)]",
2165
+ lg: "text-24"
2166
+ }
2167
+ },
2168
+ defaultVariants: {
2169
+ size: "md"
2170
+ }
2171
+ });
2172
+ var CaptionOverlay = React14.forwardRef(
2173
+ ({ className, cue, text, position, size, ...props }, ref) => {
2174
+ const displayText = cue?.text ?? text;
2175
+ if (!displayText) {
2176
+ return null;
2177
+ }
2178
+ return /* @__PURE__ */ jsx(
2179
+ "output",
2180
+ {
2181
+ ref,
2182
+ className: cn(captionOverlayVariants({ position }), className),
2183
+ "aria-live": "polite",
2184
+ "aria-label": "Video caption",
2185
+ ...props,
2186
+ children: /* @__PURE__ */ jsx("span", { className: captionTextVariants({ size }), children: displayText })
2187
+ }
2188
+ );
2189
+ }
2190
+ );
2191
+ CaptionOverlay.displayName = "CaptionOverlay";
2192
+ function parseVttTimestamp(timestamp) {
2193
+ const parts = timestamp.trim().split(":");
2194
+ let hours = 0;
2195
+ let minutes = 0;
2196
+ let seconds = 0;
2197
+ if (parts.length === 3) {
2198
+ hours = Number.parseInt(parts[0], 10);
2199
+ minutes = Number.parseInt(parts[1], 10);
2200
+ seconds = Number.parseFloat(parts[2]);
2201
+ } else if (parts.length === 2) {
2202
+ minutes = Number.parseInt(parts[0], 10);
2203
+ seconds = Number.parseFloat(parts[1]);
2204
+ }
2205
+ return hours * 3600 + minutes * 60 + seconds;
2206
+ }
2207
+ function parseVtt(vttContent) {
2208
+ const cues = [];
2209
+ const lines = vttContent.trim().split("\n");
2210
+ let i = 0;
2211
+ while (i < lines.length && !lines[i].includes("-->")) {
2212
+ i++;
2213
+ }
2214
+ while (i < lines.length) {
2215
+ const line = lines[i].trim();
2216
+ if (line.includes("-->")) {
2217
+ const [startStr, endStr] = line.split("-->").map((s) => s.trim());
2218
+ const endParts = endStr.split(" ");
2219
+ const endTime = parseVttTimestamp(endParts[0]);
2220
+ const startTime = parseVttTimestamp(startStr);
2221
+ const textLines = [];
2222
+ i++;
2223
+ while (i < lines.length && lines[i].trim() !== "" && !lines[i].includes("-->")) {
2224
+ if (!/^\d+$/.test(lines[i].trim())) {
2225
+ textLines.push(lines[i].trim());
2226
+ }
2227
+ i++;
2228
+ }
2229
+ if (textLines.length > 0) {
2230
+ cues.push({
2231
+ id: `cue-${cues.length}`,
2232
+ startTime,
2233
+ endTime,
2234
+ text: textLines.join("\n")
2235
+ });
2236
+ }
2237
+ } else {
2238
+ i++;
2239
+ }
2240
+ }
2241
+ return cues;
2242
+ }
2243
+ function stripVttTags(text) {
2244
+ return text.replace(/<\/?[^>]+(>|$)/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").trim();
2245
+ }
2246
+ function useCaptions(options = {}) {
2247
+ const { src, content, stripTags = true, currentTime: externalTime } = options;
2248
+ const [cues, setCues] = React14.useState([]);
2249
+ const [internalTime, setInternalTime] = React14.useState(0);
2250
+ const [isLoading, setIsLoading] = React14.useState(false);
2251
+ const [error, setError] = React14.useState(null);
2252
+ const currentTime = externalTime ?? internalTime;
2253
+ React14.useEffect(() => {
2254
+ if (content) {
2255
+ const parsed = parseVtt(content);
2256
+ setCues(
2257
+ stripTags ? parsed.map((cue) => ({ ...cue, text: stripVttTags(cue.text) })) : parsed
2258
+ );
2259
+ return;
2260
+ }
2261
+ if (!src) {
2262
+ setCues([]);
2263
+ return;
2264
+ }
2265
+ setIsLoading(true);
2266
+ setError(null);
2267
+ fetch(src).then((response) => {
2268
+ if (!response.ok) {
2269
+ throw new Error(`Failed to fetch captions: ${response.status}`);
2270
+ }
2271
+ return response.text();
2272
+ }).then((vttContent) => {
2273
+ const parsed = parseVtt(vttContent);
2274
+ setCues(
2275
+ stripTags ? parsed.map((cue) => ({ ...cue, text: stripVttTags(cue.text) })) : parsed
2276
+ );
2277
+ }).catch((err) => {
2278
+ setError(err instanceof Error ? err : new Error(String(err)));
2279
+ }).finally(() => {
2280
+ setIsLoading(false);
2281
+ });
2282
+ }, [src, content, stripTags]);
2283
+ const activeCue = React14.useMemo(() => {
2284
+ return cues.find(
2285
+ (cue) => currentTime >= cue.startTime && currentTime <= cue.endTime
2286
+ ) ?? null;
2287
+ }, [cues, currentTime]);
2288
+ const handleSetCurrentTime = React14.useCallback((time) => {
2289
+ setInternalTime(time);
2290
+ }, []);
2291
+ return {
2292
+ cues,
2293
+ activeCue,
2294
+ setCurrentTime: handleSetCurrentTime,
2295
+ isLoading,
2296
+ error
2297
+ };
2298
+ }
2299
+ function useVideoKeyboard({
2300
+ videoRef,
2301
+ enabled = true,
2302
+ seekAmount = 5,
2303
+ volumeStep = 0.1,
2304
+ onTogglePlay,
2305
+ onToggleFullscreen,
2306
+ onToggleCaptions,
2307
+ onShowControls
2308
+ }) {
2309
+ const handleKeyDown = React14.useCallback(
2310
+ (e) => {
2311
+ if (!enabled) return;
2312
+ const video = videoRef.current;
2313
+ if (!video) return;
2314
+ const target = e.target;
2315
+ if (target.tagName === "BUTTON" || target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.closest("button") || target.closest("input") || target.closest("[role='slider']")) {
2316
+ return;
2317
+ }
2318
+ let handled = false;
2319
+ switch (e.key) {
2320
+ // Play/Pause
2321
+ case " ":
2322
+ case "Spacebar":
2323
+ case "k":
2324
+ if (onTogglePlay) {
2325
+ onTogglePlay();
2326
+ } else {
2327
+ if (video.paused) {
2328
+ video.play().catch(() => {
2329
+ });
2330
+ } else {
2331
+ video.pause();
2332
+ }
2333
+ }
2334
+ handled = true;
2335
+ break;
2336
+ // Seek backward
2337
+ case "ArrowLeft":
2338
+ case "j":
2339
+ video.currentTime = Math.max(0, video.currentTime - seekAmount);
2340
+ handled = true;
2341
+ break;
2342
+ // Seek forward
2343
+ case "ArrowRight":
2344
+ case "l":
2345
+ video.currentTime = Math.min(
2346
+ video.duration || 0,
2347
+ video.currentTime + seekAmount
2348
+ );
2349
+ handled = true;
2350
+ break;
2351
+ // Volume up
2352
+ case "ArrowUp":
2353
+ video.volume = Math.min(1, video.volume + volumeStep);
2354
+ video.muted = false;
2355
+ handled = true;
2356
+ break;
2357
+ // Volume down
2358
+ case "ArrowDown":
2359
+ video.volume = Math.max(0, video.volume - volumeStep);
2360
+ handled = true;
2361
+ break;
2362
+ // Toggle mute
2363
+ case "m":
2364
+ case "M":
2365
+ video.muted = !video.muted;
2366
+ handled = true;
2367
+ break;
2368
+ // Toggle fullscreen
2369
+ case "f":
2370
+ case "F":
2371
+ onToggleFullscreen?.();
2372
+ handled = true;
2373
+ break;
2374
+ // Toggle captions
2375
+ case "c":
2376
+ case "C":
2377
+ onToggleCaptions?.();
2378
+ handled = true;
2379
+ break;
2380
+ // Jump to start
2381
+ case "Home":
2382
+ video.currentTime = 0;
2383
+ handled = true;
2384
+ break;
2385
+ // Jump to end
2386
+ case "End":
2387
+ video.currentTime = video.duration || 0;
2388
+ handled = true;
2389
+ break;
2390
+ // Number keys for percentage seeking (0-9)
2391
+ case "0":
2392
+ case "1":
2393
+ case "2":
2394
+ case "3":
2395
+ case "4":
2396
+ case "5":
2397
+ case "6":
2398
+ case "7":
2399
+ case "8":
2400
+ case "9":
2401
+ if (video.duration) {
2402
+ const percent = parseInt(e.key, 10) / 10;
2403
+ video.currentTime = video.duration * percent;
2404
+ handled = true;
2405
+ }
2406
+ break;
2407
+ }
2408
+ if (handled) {
2409
+ e.preventDefault();
2410
+ e.stopPropagation();
2411
+ onShowControls?.();
2412
+ }
2413
+ },
2414
+ [
2415
+ enabled,
2416
+ videoRef,
2417
+ seekAmount,
2418
+ volumeStep,
2419
+ onTogglePlay,
2420
+ onToggleFullscreen,
2421
+ onToggleCaptions,
2422
+ onShowControls
2423
+ ]
2424
+ );
2425
+ const containerProps = React14.useMemo(
2426
+ () => ({
2427
+ onKeyDown: handleKeyDown,
2428
+ tabIndex: 0,
2429
+ role: "application",
2430
+ "aria-label": "Video player, press space to play or pause"
2431
+ }),
2432
+ [handleKeyDown]
2433
+ );
2434
+ return {
2435
+ handleKeyDown,
2436
+ containerProps
2437
+ };
2438
+ }
2439
+ var videoPlayerVariants = tv({
2440
+ base: [
2441
+ "relative",
2442
+ "bg-black",
2443
+ "overflow-hidden",
2444
+ // Focus styling for keyboard navigation
2445
+ "focus:outline-none",
2446
+ "focus-visible:ring-2",
2447
+ "focus-visible:ring-white/50"
2448
+ ],
2449
+ variants: {
2450
+ aspectRatio: {
2451
+ "16/9": "aspect-video",
2452
+ "4/3": "aspect-[4/3]",
2453
+ "1/1": "aspect-square",
2454
+ "9/16": "aspect-[9/16]",
2455
+ auto: ""
2456
+ },
2457
+ rounded: {
2458
+ none: "",
2459
+ sm: "rounded-4",
2460
+ md: "rounded-8",
2461
+ lg: "rounded-12"
2462
+ }
2463
+ },
2464
+ defaultVariants: {
2465
+ aspectRatio: "16/9",
2466
+ rounded: "none"
2467
+ }
2468
+ });
2469
+ var mediaControllerVariants = tv({
2470
+ base: [
2471
+ "absolute inset-0",
2472
+ "w-full h-full",
2473
+ // Button styling - transparent base, hover shows background
2474
+ "[--media-control-background:transparent]",
2475
+ "[--media-control-hover-background:var(--color-video-player-button-bg-hover)]",
2476
+ "[--media-control-padding:8px]",
2477
+ "[--media-control-height:36px]",
2478
+ "[--media-button-icon-width:20px]",
2479
+ "[--media-button-icon-height:20px]",
2480
+ // Progress bar / range styling
2481
+ "[--media-range-track-background:var(--color-video-player-progress-bg)]",
2482
+ "[--media-range-bar-color:var(--color-video-player-progress-fill)]",
2483
+ "[--media-range-track-height:4px]",
2484
+ "[--media-range-track-border-radius:2px]",
2485
+ "[--media-range-thumb-background:var(--color-video-player-progress-fill)]",
2486
+ "[--media-range-thumb-height:12px]",
2487
+ "[--media-range-thumb-width:12px]",
2488
+ "[--media-range-thumb-border-radius:50%]",
2489
+ // Text/icon colors
2490
+ "[--media-icon-color:var(--color-video-player-controls-text)]",
2491
+ "[--media-primary-color:var(--color-video-player-controls-text)]",
2492
+ "[--media-secondary-color:transparent]",
2493
+ "[--media-text-color:var(--color-video-player-controls-text)]",
2494
+ "[--media-font-size:14px]",
2495
+ // Time display styling
2496
+ "[--media-time-display-background:transparent]"
2497
+ ]
2498
+ });
2499
+ var mediaButtonStyles = {
2500
+ padding: "8px",
2501
+ borderRadius: "50%",
2502
+ // Tooltip styling - consistent across all buttons
2503
+ "--media-tooltip-background": "var(--color-video-player-tooltip-bg)",
2504
+ "--media-tooltip-arrow-display": "none",
2505
+ "--media-tooltip-distance": "8px"
2506
+ };
2507
+ var timeRangeStyles = {
2508
+ flex: 1,
2509
+ background: "transparent",
2510
+ // Preview tooltip styling - consistent with button tooltips
2511
+ "--media-box-arrow-display": "none",
2512
+ "--media-preview-box-margin": "0 0 8px 0",
2513
+ "--media-preview-time-margin": "0 0 8px 0",
2514
+ "--media-preview-time-background": "var(--color-video-player-tooltip-bg)"
2515
+ };
2516
+ var volumeRangeStyles = {
2517
+ width: "80px",
2518
+ background: "transparent",
2519
+ // Tooltip styling - consistent with button tooltips
2520
+ "--media-tooltip-background": "var(--color-video-player-tooltip-bg)",
2521
+ "--media-tooltip-arrow-display": "none",
2522
+ "--media-tooltip-distance": "8px"
2523
+ };
2524
+ var timeDisplayStyles = {
2525
+ background: "transparent",
2526
+ fontFamily: "monospace",
2527
+ fontSize: "14px",
2528
+ color: "white",
2529
+ whiteSpace: "nowrap"
2530
+ };
2531
+ var controlBarVariants = tv({
2532
+ base: [
2533
+ // Layout handled in inline styles, but we need flex
2534
+ "flex items-center",
2535
+ // Background using semantic token
2536
+ "bg-video-player-controls-bg",
2537
+ // Animation
2538
+ "transition-all duration-300"
2539
+ ],
2540
+ variants: {
2541
+ visible: {
2542
+ true: "opacity-100 translate-y-0",
2543
+ false: "opacity-0 translate-y-16 pointer-events-none"
2544
+ }
2545
+ },
2546
+ defaultVariants: {
2547
+ visible: true
2548
+ }
2549
+ });
2550
+ var controlButtonVariants = tv({
2551
+ base: [
2552
+ "flex items-center justify-center",
2553
+ "p-8 rounded-full",
2554
+ // Transparent by default, background on hover
2555
+ "bg-transparent",
2556
+ "text-video-player-controls-text",
2557
+ "hover:bg-video-player-button-bg-hover",
2558
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-video-player-progress-bg",
2559
+ "transition-colors duration-150",
2560
+ "cursor-pointer"
2561
+ ]
2562
+ });
2563
+ var loadingOverlayVariants = tv({
2564
+ base: [
2565
+ "absolute inset-0",
2566
+ "flex items-center justify-center",
2567
+ "bg-black/50",
2568
+ "pointer-events-none",
2569
+ "z-10"
2570
+ ]
2571
+ });
2572
+ function useHlsInternal(videoRef, src, enabled) {
2573
+ const [isLoading, setIsLoading] = React14.useState(true);
2574
+ const [error, setError] = React14.useState(null);
2575
+ const hlsRef = React14.useRef(null);
2576
+ React14.useEffect(() => {
2577
+ if (!src || !videoRef.current) {
2578
+ return;
2579
+ }
2580
+ const video = videoRef.current;
2581
+ const isHlsSource = src.includes(".m3u8");
2582
+ if (!isHlsSource) {
2583
+ video.src = src;
2584
+ setIsLoading(false);
2585
+ return;
2586
+ }
2587
+ if (video.canPlayType("application/vnd.apple.mpegurl")) {
2588
+ video.src = src;
2589
+ setIsLoading(false);
2590
+ return;
2591
+ }
2592
+ const loadHls = async () => {
2593
+ try {
2594
+ const HlsModule = await import('hls.js');
2595
+ const Hls = HlsModule.default;
2596
+ if (!Hls.isSupported()) {
2597
+ video.src = src;
2598
+ setIsLoading(false);
2599
+ return;
2600
+ }
2601
+ const hls = new Hls({
2602
+ enableWorker: true,
2603
+ lowLatencyMode: false
2604
+ });
2605
+ hls.loadSource(src);
2606
+ hls.attachMedia(video);
2607
+ hls.on(Hls.Events.MANIFEST_PARSED, () => {
2608
+ setIsLoading(false);
2609
+ });
2610
+ hls.on(
2611
+ Hls.Events.ERROR,
2612
+ (_event, data) => {
2613
+ if (data.fatal) {
2614
+ setError(new Error(`HLS error: ${data.details}`));
2615
+ setIsLoading(false);
2616
+ }
2617
+ }
2618
+ );
2619
+ hlsRef.current = hls;
2620
+ } catch {
2621
+ video.src = src;
2622
+ setIsLoading(false);
2623
+ }
2624
+ };
2625
+ loadHls();
2626
+ return () => {
2627
+ if (hlsRef.current) {
2628
+ hlsRef.current.destroy();
2629
+ hlsRef.current = null;
2630
+ }
2631
+ };
2632
+ }, [enabled, src, videoRef]);
2633
+ return { isLoading, error };
2634
+ }
2635
+ var VideoPlayer = React14.forwardRef(
2636
+ ({
2637
+ className,
2638
+ src,
2639
+ cloudflare,
2640
+ poster,
2641
+ captionsSrc,
2642
+ autoPlay = false,
2643
+ loop = false,
2644
+ muted = false,
2645
+ controls = true,
2646
+ autoHideControls = true,
2647
+ autoHideDelay = 3e3,
2648
+ captionsEnabled: initialCaptionsEnabled = false,
2649
+ aspectRatio,
2650
+ rounded,
2651
+ onPlay,
2652
+ onPause,
2653
+ onEnded,
2654
+ onTimeUpdate,
2655
+ onError,
2656
+ videoRef: externalVideoRef,
2657
+ ...props
2658
+ }, ref) => {
2659
+ const containerRef = React14.useRef(null);
2660
+ const internalVideoRef = React14.useRef(null);
2661
+ const controlsTimeoutRef = React14.useRef(null);
2662
+ const [isPlaying, setIsPlaying] = React14.useState(false);
2663
+ const [currentTime, setCurrentTime] = React14.useState(0);
2664
+ const [controlsVisible, setControlsVisible] = React14.useState(true);
2665
+ const [captionsEnabled, setCaptionsEnabled] = React14.useState(
2666
+ initialCaptionsEnabled
2667
+ );
2668
+ const [isFullscreen, setIsFullscreen] = React14.useState(false);
2669
+ const videoSrc = React14.useMemo(() => {
2670
+ if (cloudflare) {
2671
+ return `https://customer-${cloudflare.customerCode}.cloudflarestream.com/${cloudflare.videoId}/manifest/video.m3u8`;
2672
+ }
2673
+ return src;
2674
+ }, [cloudflare, src]);
2675
+ const { isLoading, error: hlsError } = useHlsInternal(
2676
+ internalVideoRef,
2677
+ videoSrc,
2678
+ true
2679
+ );
2680
+ const { activeCue } = useCaptions({
2681
+ src: captionsSrc,
2682
+ currentTime
2683
+ });
2684
+ React14.useEffect(() => {
2685
+ if (externalVideoRef) {
2686
+ externalVideoRef.current = internalVideoRef.current;
2687
+ }
2688
+ }, [externalVideoRef]);
2689
+ React14.useImperativeHandle(
2690
+ ref,
2691
+ () => containerRef.current
2692
+ );
2693
+ React14.useEffect(() => {
2694
+ if (hlsError && onError) {
2695
+ onError(hlsError);
2696
+ }
2697
+ }, [hlsError, onError]);
2698
+ React14.useEffect(() => {
2699
+ const video = internalVideoRef.current;
2700
+ if (!video) return;
2701
+ const handlePlay = () => {
2702
+ setIsPlaying(true);
2703
+ onPlay?.();
2704
+ };
2705
+ const handlePause = () => {
2706
+ setIsPlaying(false);
2707
+ onPause?.();
2708
+ };
2709
+ const handleEnded = () => {
2710
+ setIsPlaying(false);
2711
+ onEnded?.();
2712
+ };
2713
+ const handleTimeUpdate = () => {
2714
+ setCurrentTime(video.currentTime);
2715
+ onTimeUpdate?.(video.currentTime);
2716
+ };
2717
+ const handleCanPlay = () => {
2718
+ if (autoPlay) {
2719
+ video.play().catch(() => {
2720
+ });
2721
+ }
2722
+ };
2723
+ video.addEventListener("play", handlePlay);
2724
+ video.addEventListener("pause", handlePause);
2725
+ video.addEventListener("ended", handleEnded);
2726
+ video.addEventListener("timeupdate", handleTimeUpdate);
2727
+ video.addEventListener("canplay", handleCanPlay);
2728
+ return () => {
2729
+ video.removeEventListener("play", handlePlay);
2730
+ video.removeEventListener("pause", handlePause);
2731
+ video.removeEventListener("ended", handleEnded);
2732
+ video.removeEventListener("timeupdate", handleTimeUpdate);
2733
+ video.removeEventListener("canplay", handleCanPlay);
2734
+ };
2735
+ }, [autoPlay, onPlay, onPause, onEnded, onTimeUpdate]);
2736
+ React14.useEffect(() => {
2737
+ if (!autoHideControls || !isPlaying || !controlsVisible) return;
2738
+ controlsTimeoutRef.current = setTimeout(() => {
2739
+ setControlsVisible(false);
2740
+ }, autoHideDelay);
2741
+ return () => {
2742
+ if (controlsTimeoutRef.current) {
2743
+ clearTimeout(controlsTimeoutRef.current);
2744
+ }
2745
+ };
2746
+ }, [autoHideControls, isPlaying, controlsVisible, autoHideDelay]);
2747
+ React14.useEffect(() => {
2748
+ const handleFullscreenChange = () => {
2749
+ setIsFullscreen(!!document.fullscreenElement);
2750
+ };
2751
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
2752
+ document.addEventListener(
2753
+ "webkitfullscreenchange",
2754
+ handleFullscreenChange
2755
+ );
2756
+ return () => {
2757
+ document.removeEventListener(
2758
+ "fullscreenchange",
2759
+ handleFullscreenChange
2760
+ );
2761
+ document.removeEventListener(
2762
+ "webkitfullscreenchange",
2763
+ handleFullscreenChange
2764
+ );
2765
+ };
2766
+ }, []);
2767
+ const togglePlay = React14.useCallback(() => {
2768
+ const video = internalVideoRef.current;
2769
+ if (!video) return;
2770
+ if (video.paused) {
2771
+ video.play().catch(() => {
2772
+ });
2773
+ } else {
2774
+ video.pause();
2775
+ }
2776
+ }, []);
2777
+ const toggleCaptions = React14.useCallback(() => {
2778
+ setCaptionsEnabled((prev) => !prev);
2779
+ }, []);
2780
+ const toggleFullscreen = React14.useCallback(() => {
2781
+ if (!document.fullscreenElement) {
2782
+ containerRef.current?.requestFullscreen();
2783
+ } else {
2784
+ document.exitFullscreen();
2785
+ }
2786
+ }, []);
2787
+ const showControls = React14.useCallback(() => {
2788
+ setControlsVisible(true);
2789
+ if (controlsTimeoutRef.current) {
2790
+ clearTimeout(controlsTimeoutRef.current);
2791
+ }
2792
+ }, []);
2793
+ const handleMouseLeave = React14.useCallback(() => {
2794
+ if (autoHideControls && isPlaying) {
2795
+ setControlsVisible(false);
2796
+ }
2797
+ }, [autoHideControls, isPlaying]);
2798
+ const { containerProps: keyboardProps } = useVideoKeyboard({
2799
+ videoRef: internalVideoRef,
2800
+ onTogglePlay: togglePlay,
2801
+ onToggleFullscreen: toggleFullscreen,
2802
+ onToggleCaptions: captionsSrc ? toggleCaptions : void 0,
2803
+ onShowControls: showControls
2804
+ });
2805
+ return (
2806
+ // biome-ignore lint/a11y/noStaticElementInteractions: role is applied via keyboardProps spread
2807
+ /* @__PURE__ */ jsxs(
2808
+ "div",
2809
+ {
2810
+ ref: containerRef,
2811
+ className: cn(videoPlayerVariants({ aspectRatio, rounded }), className),
2812
+ onMouseMove: showControls,
2813
+ onMouseLeave: handleMouseLeave,
2814
+ ...keyboardProps,
2815
+ ...props,
2816
+ children: [
2817
+ controls ? /* @__PURE__ */ jsxs(
2818
+ MediaController,
2819
+ {
2820
+ noAutohide: true,
2821
+ className: mediaControllerVariants(),
2822
+ children: [
2823
+ /* @__PURE__ */ jsx(
2824
+ "video",
2825
+ {
2826
+ ref: internalVideoRef,
2827
+ slot: "media",
2828
+ poster,
2829
+ loop,
2830
+ muted,
2831
+ playsInline: true,
2832
+ crossOrigin: "anonymous",
2833
+ className: "w-full h-full object-contain"
2834
+ }
2835
+ ),
2836
+ /* @__PURE__ */ jsx(MediaLoadingIndicator, { slot: "centered-chrome", noAutohide: true }),
2837
+ /* @__PURE__ */ jsx(
2838
+ "div",
2839
+ {
2840
+ onClick: togglePlay,
2841
+ className: "absolute inset-0 cursor-pointer z-[1]",
2842
+ "aria-hidden": "true"
2843
+ }
2844
+ ),
2845
+ /* @__PURE__ */ jsxs(
2846
+ MediaControlBar,
2847
+ {
2848
+ className: controlBarVariants({ visible: controlsVisible }),
2849
+ onClick: (e) => e.stopPropagation(),
2850
+ style: {
2851
+ position: "absolute",
2852
+ left: "24px",
2853
+ right: "24px",
2854
+ bottom: "24px",
2855
+ gap: "12px",
2856
+ padding: "8px 16px",
2857
+ borderRadius: "9999px",
2858
+ backdropFilter: "blur(10px)",
2859
+ WebkitBackdropFilter: "blur(10px)",
2860
+ zIndex: 2
2861
+ },
2862
+ children: [
2863
+ /* @__PURE__ */ jsx(MediaPlayButton, { style: mediaButtonStyles }),
2864
+ /* @__PURE__ */ jsx(MediaMuteButton, { style: mediaButtonStyles }),
2865
+ /* @__PURE__ */ jsx(MediaVolumeRange, { style: volumeRangeStyles }),
2866
+ /* @__PURE__ */ jsx(
2867
+ MediaTimeDisplay,
2868
+ {
2869
+ style: timeDisplayStyles,
2870
+ showDuration: true,
2871
+ noToggle: true
2872
+ }
2873
+ ),
2874
+ /* @__PURE__ */ jsx(MediaTimeRange, { style: timeRangeStyles }),
2875
+ captionsSrc && /* @__PURE__ */ jsx(
2876
+ "button",
2877
+ {
2878
+ type: "button",
2879
+ className: controlButtonVariants(),
2880
+ onClick: (e) => {
2881
+ e.stopPropagation();
2882
+ toggleCaptions();
2883
+ },
2884
+ "aria-label": captionsEnabled ? "Disable captions" : "Enable captions",
2885
+ "aria-pressed": captionsEnabled,
2886
+ children: /* @__PURE__ */ jsx(CaptionsIcon, { enabled: captionsEnabled })
2887
+ }
2888
+ ),
2889
+ /* @__PURE__ */ jsx(
2890
+ "button",
2891
+ {
2892
+ type: "button",
2893
+ className: controlButtonVariants(),
2894
+ onClick: (e) => {
2895
+ e.stopPropagation();
2896
+ toggleFullscreen();
2897
+ },
2898
+ "aria-label": isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
2899
+ children: /* @__PURE__ */ jsx(FullscreenIcon, { isFullscreen })
2900
+ }
2901
+ )
2902
+ ]
2903
+ }
2904
+ )
2905
+ ]
2906
+ }
2907
+ ) : (
2908
+ /* Video without controls */
2909
+ /* @__PURE__ */ jsx(
2910
+ "video",
2911
+ {
2912
+ ref: internalVideoRef,
2913
+ poster,
2914
+ loop,
2915
+ muted,
2916
+ playsInline: true,
2917
+ crossOrigin: "anonymous",
2918
+ className: "w-full h-full object-contain",
2919
+ onClick: togglePlay
2920
+ }
2921
+ )
2922
+ ),
2923
+ isLoading && /* @__PURE__ */ jsx("div", { className: loadingOverlayVariants(), children: /* @__PURE__ */ jsx("div", { className: "w-40 h-40 border-3 border-white/30 border-t-white rounded-full animate-spin" }) }),
2924
+ hlsError && /* @__PURE__ */ jsx("div", { className: loadingOverlayVariants(), children: /* @__PURE__ */ jsxs("div", { className: "text-white text-center px-16", children: [
2925
+ /* @__PURE__ */ jsx("p", { className: "typography-body-sm-sm", children: "Failed to load video" }),
2926
+ /* @__PURE__ */ jsx("p", { className: "typography-caption text-white/60 mt-4", children: hlsError.message })
2927
+ ] }) }),
2928
+ captionsEnabled && activeCue && /* @__PURE__ */ jsx(CaptionOverlay, { cue: activeCue })
2929
+ ]
2930
+ }
2931
+ )
2932
+ );
2933
+ }
2934
+ );
2935
+ VideoPlayer.displayName = "VideoPlayer";
2936
+ var CaptionsIcon = ({ enabled }) => /* @__PURE__ */ jsx(
2937
+ "svg",
2938
+ {
2939
+ className: "w-20 h-20",
2940
+ viewBox: "0 0 24 24",
2941
+ fill: "currentColor",
2942
+ "aria-hidden": "true",
2943
+ children: enabled ? (
2944
+ // Captions On
2945
+ /* @__PURE__ */ jsx("path", { d: "M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z" })
2946
+ ) : (
2947
+ // Captions Off (with strike-through)
2948
+ /* @__PURE__ */ jsxs(Fragment, { children: [
2949
+ /* @__PURE__ */ jsx("path", { d: "M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z" }),
2950
+ /* @__PURE__ */ jsx(
2951
+ "line",
2952
+ {
2953
+ x1: "4",
2954
+ y1: "20",
2955
+ x2: "20",
2956
+ y2: "4",
2957
+ stroke: "currentColor",
2958
+ strokeWidth: "2"
2959
+ }
2960
+ )
2961
+ ] })
2962
+ )
2963
+ }
2964
+ );
2965
+ var FullscreenIcon = ({ isFullscreen }) => /* @__PURE__ */ jsx(
2966
+ "svg",
2967
+ {
2968
+ className: "w-20 h-20",
2969
+ viewBox: "0 0 24 24",
2970
+ fill: "none",
2971
+ stroke: "currentColor",
2972
+ strokeWidth: "2",
2973
+ strokeLinecap: "round",
2974
+ strokeLinejoin: "round",
2975
+ "aria-hidden": "true",
2976
+ children: isFullscreen ? (
2977
+ // Minimize (exit fullscreen)
2978
+ /* @__PURE__ */ jsxs(Fragment, { children: [
2979
+ /* @__PURE__ */ jsx("polyline", { points: "4 14 10 14 10 20" }),
2980
+ /* @__PURE__ */ jsx("polyline", { points: "20 10 14 10 14 4" }),
2981
+ /* @__PURE__ */ jsx("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
2982
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
2983
+ ] })
2984
+ ) : (
2985
+ // Maximize (enter fullscreen)
2986
+ /* @__PURE__ */ jsxs(Fragment, { children: [
2987
+ /* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
2988
+ /* @__PURE__ */ jsx("polyline", { points: "9 21 3 21 3 15" }),
2989
+ /* @__PURE__ */ jsx("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
2990
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
2991
+ ] })
2992
+ )
2993
+ }
2994
+ );
1811
2995
  function GridOverlay({
1812
2996
  columnOpacity = 0.15,
1813
2997
  borderOpacity = 0.3,
@@ -1962,49 +3146,648 @@ function DevToolbar({ defaultExpanded = false }) {
1962
3146
  className: `bg-gray-1100 rounded-radius-16 shadow-lg flex flex-col items-center overflow-hidden px-12 py-8 ${isExpanded ? "gap-4" : ""}`,
1963
3147
  children: [
1964
3148
  /* @__PURE__ */ jsx(
1965
- "div",
3149
+ "div",
3150
+ {
3151
+ className: `
3152
+ grid transition-all duration-300 ease-out
3153
+ ${isExpanded ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"}
3154
+ `,
3155
+ children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx(
3156
+ "button",
3157
+ {
3158
+ type: "button",
3159
+ onClick: toggleGrid,
3160
+ className: `
3161
+ size-40 rounded-full flex items-center justify-center transition-colors
3162
+ ${showGrid ? "text-gray-50" : "text-gray-400 hover:text-gray-50 hover:bg-alpha-white-10"}
3163
+ `,
3164
+ title: "Toggle Grid (\u2318G)",
3165
+ "aria-label": "Toggle grid overlay",
3166
+ children: /* @__PURE__ */ jsx(GridIcon, { active: showGrid })
3167
+ }
3168
+ ) })
3169
+ }
3170
+ ),
3171
+ /* @__PURE__ */ jsx(
3172
+ "button",
3173
+ {
3174
+ type: "button",
3175
+ onMouseDown: handleBarMouseDown,
3176
+ onTouchStart: handleBarTouchStart,
3177
+ onClick: handleBarClick,
3178
+ className: `
3179
+ w-32 h-4 bg-gray-50 rounded-full transition-opacity
3180
+ ${isDragging ? "opacity-100 cursor-grabbing" : "opacity-60 hover:opacity-100 cursor-grab"}
3181
+ `,
3182
+ "aria-label": isExpanded ? "Close dev tools" : "Open dev tools"
3183
+ }
3184
+ )
3185
+ ]
3186
+ }
3187
+ )
3188
+ }
3189
+ )
3190
+ ] });
3191
+ }
3192
+ var dialogBackdropVariants = tv({
3193
+ base: [
3194
+ // Fixed positioning to cover viewport
3195
+ "fixed inset-0",
3196
+ // Semi-transparent black background using alpha token
3197
+ "bg-alpha-black-50",
3198
+ // Smooth opacity transition
3199
+ "transition-opacity duration-200",
3200
+ // Animation states
3201
+ "data-[starting-style]:opacity-0",
3202
+ "data-[ending-style]:opacity-0",
3203
+ // Ensure backdrop covers full viewport on iOS
3204
+ "min-h-dvh"
3205
+ ]
3206
+ });
3207
+ var dialogPopupVariants = tv({
3208
+ base: [
3209
+ // Fixed positioning, centered
3210
+ "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2",
3211
+ // Layout
3212
+ "flex flex-col",
3213
+ // Max dimensions with viewport margin (24px on each side = 48px total)
3214
+ "max-h-[calc(100vh-48px)] max-w-[calc(100vw-48px)]",
3215
+ // Ensure above backdrop
3216
+ "z-50",
3217
+ // Animation
3218
+ "transition-all duration-200",
3219
+ "data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
3220
+ "data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
3221
+ // Focus outline
3222
+ "outline-none"
3223
+ ],
3224
+ variants: {
3225
+ size: {
3226
+ sm: "w-full sm:max-w-[400px]",
3227
+ md: "w-full sm:max-w-[560px]",
3228
+ lg: "w-full sm:max-w-[720px]",
3229
+ xl: "w-full sm:max-w-[960px]",
3230
+ full: "w-[calc(100vw-48px)] h-[calc(100vh-48px)]"
3231
+ },
3232
+ variant: {
3233
+ default: [
3234
+ // Background - uses overlay background token
3235
+ "bg-overlay-background",
3236
+ // Border - uses overlay border token
3237
+ "border border-overlay-border",
3238
+ // Text - uses overlay text token
3239
+ "text-overlay-text",
3240
+ // Border radius - uses surface overlay token
3241
+ "rounded-surface-overlay",
3242
+ // Shadow for elevation
3243
+ "shadow-xl"
3244
+ ],
3245
+ minimal: [
3246
+ // Transparent background, no border/shadow
3247
+ "bg-black",
3248
+ "border-0",
3249
+ "text-white",
3250
+ "rounded-8",
3251
+ "shadow-none",
3252
+ "overflow-hidden"
3253
+ ]
3254
+ }
3255
+ },
3256
+ compoundVariants: [
3257
+ // Default variant padding by size
3258
+ { variant: "default", size: "sm", class: "p-24" },
3259
+ { variant: "default", size: "md", class: "p-32" },
3260
+ { variant: "default", size: "lg", class: "p-32" },
3261
+ { variant: "default", size: "xl", class: "p-40" },
3262
+ { variant: "default", size: "full", class: "p-40" },
3263
+ // Minimal variant has no padding
3264
+ { variant: "minimal", size: "sm", class: "p-0" },
3265
+ { variant: "minimal", size: "md", class: "p-0" },
3266
+ { variant: "minimal", size: "lg", class: "p-0" },
3267
+ { variant: "minimal", size: "xl", class: "p-0" },
3268
+ { variant: "minimal", size: "full", class: "p-0" }
3269
+ ],
3270
+ defaultVariants: {
3271
+ size: "md",
3272
+ variant: "default"
3273
+ }
3274
+ });
3275
+ var DialogRoot = ({ children, ...props }) => {
3276
+ return /* @__PURE__ */ jsx(Dialog$1.Root, { ...props, children });
3277
+ };
3278
+ var DialogTrigger = React14.forwardRef(
3279
+ ({ className, children, ...props }, ref) => {
3280
+ const isSingleElement = React14.isValidElement(children);
3281
+ if (isSingleElement) {
3282
+ return /* @__PURE__ */ jsx(
3283
+ Dialog$1.Trigger,
3284
+ {
3285
+ ref,
3286
+ className,
3287
+ render: children,
3288
+ ...props
3289
+ }
3290
+ );
3291
+ }
3292
+ return /* @__PURE__ */ jsx(Dialog$1.Trigger, { ref, className, ...props, children });
3293
+ }
3294
+ );
3295
+ DialogTrigger.displayName = "DialogTrigger";
3296
+ var DialogPortal = ({ children, ...props }) => {
3297
+ return /* @__PURE__ */ jsx(Dialog$1.Portal, { ...props, children });
3298
+ };
3299
+ var DialogBackdrop = React14.forwardRef(
3300
+ ({ className, ...props }, ref) => {
3301
+ return /* @__PURE__ */ jsx(
3302
+ Dialog$1.Backdrop,
3303
+ {
3304
+ ref,
3305
+ className: cn(dialogBackdropVariants(), className),
3306
+ ...props
3307
+ }
3308
+ );
3309
+ }
3310
+ );
3311
+ DialogBackdrop.displayName = "DialogBackdrop";
3312
+ var DialogPopup = React14.forwardRef(
3313
+ ({ className, size, variant, ...props }, ref) => {
3314
+ return /* @__PURE__ */ jsx(
3315
+ Dialog$1.Popup,
3316
+ {
3317
+ ref,
3318
+ className: cn(dialogPopupVariants({ size, variant }), className),
3319
+ ...props
3320
+ }
3321
+ );
3322
+ }
3323
+ );
3324
+ DialogPopup.displayName = "DialogPopup";
3325
+ var DialogTitle = React14.forwardRef(
3326
+ ({ className, ...props }, ref) => {
3327
+ return /* @__PURE__ */ jsx(
3328
+ Dialog$1.Title,
3329
+ {
3330
+ ref,
3331
+ className: cn("typography-h4-md font-semibold mb-8", className),
3332
+ ...props
3333
+ }
3334
+ );
3335
+ }
3336
+ );
3337
+ DialogTitle.displayName = "DialogTitle";
3338
+ var DialogDescription = React14.forwardRef(({ className, ...props }, ref) => {
3339
+ return /* @__PURE__ */ jsx(
3340
+ Dialog$1.Description,
3341
+ {
3342
+ ref,
3343
+ className: cn("typography-body-md-md text-overlay-text-muted", className),
3344
+ ...props
3345
+ }
3346
+ );
3347
+ });
3348
+ DialogDescription.displayName = "DialogDescription";
3349
+ var DialogClose = React14.forwardRef(
3350
+ ({ className, ...props }, ref) => {
3351
+ return /* @__PURE__ */ jsx(
3352
+ Dialog$1.Close,
3353
+ {
3354
+ ref,
3355
+ className: cn(
3356
+ "absolute right-16 top-16 rounded-surface-ui-small p-8",
3357
+ "text-overlay-text-muted hover:text-overlay-text",
3358
+ "hover:bg-bg-section",
3359
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
3360
+ "transition-colors duration-150",
3361
+ className
3362
+ ),
3363
+ ...props
3364
+ }
3365
+ );
3366
+ }
3367
+ );
3368
+ DialogClose.displayName = "DialogClose";
3369
+ var DialogBody = React14.forwardRef(
3370
+ ({ className, ...props }, ref) => {
3371
+ return /* @__PURE__ */ jsx(
3372
+ "div",
3373
+ {
3374
+ ref,
3375
+ className: cn("flex-1 overflow-y-auto", className),
3376
+ ...props
3377
+ }
3378
+ );
3379
+ }
3380
+ );
3381
+ DialogBody.displayName = "DialogBody";
3382
+ var DialogFooter = React14.forwardRef(
3383
+ ({ className, ...props }, ref) => {
3384
+ return /* @__PURE__ */ jsx(
3385
+ "div",
3386
+ {
3387
+ ref,
3388
+ className: cn(
3389
+ "flex items-center justify-end gap-12 pt-24 mt-auto",
3390
+ className
3391
+ ),
3392
+ ...props
3393
+ }
3394
+ );
3395
+ }
3396
+ );
3397
+ DialogFooter.displayName = "DialogFooter";
3398
+ var Dialog = ({
3399
+ children,
3400
+ trigger,
3401
+ title,
3402
+ description,
3403
+ size = "md",
3404
+ variant = "default",
3405
+ showClose = true,
3406
+ open,
3407
+ defaultOpen,
3408
+ onOpenChange,
3409
+ className
3410
+ }) => {
3411
+ return /* @__PURE__ */ jsxs(
3412
+ DialogRoot,
3413
+ {
3414
+ open,
3415
+ defaultOpen,
3416
+ onOpenChange,
3417
+ children: [
3418
+ trigger && /* @__PURE__ */ jsx(DialogTrigger, { children: trigger }),
3419
+ /* @__PURE__ */ jsxs(DialogPortal, { children: [
3420
+ /* @__PURE__ */ jsx(DialogBackdrop, {}),
3421
+ /* @__PURE__ */ jsxs(DialogPopup, { size, variant, className, children: [
3422
+ showClose && /* @__PURE__ */ jsxs(DialogClose, { children: [
3423
+ /* @__PURE__ */ jsx(
3424
+ "svg",
1966
3425
  {
1967
- className: `
1968
- grid transition-all duration-300 ease-out
1969
- ${isExpanded ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"}
1970
- `,
1971
- children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx(
1972
- "button",
3426
+ width: "16",
3427
+ height: "16",
3428
+ viewBox: "0 0 16 16",
3429
+ fill: "none",
3430
+ "aria-hidden": "true",
3431
+ children: /* @__PURE__ */ jsx(
3432
+ "path",
1973
3433
  {
1974
- type: "button",
1975
- onClick: toggleGrid,
1976
- className: `
1977
- size-40 rounded-full flex items-center justify-center transition-colors
1978
- ${showGrid ? "text-gray-50" : "text-gray-400 hover:text-gray-50 hover:bg-alpha-white-10"}
1979
- `,
1980
- title: "Toggle Grid (\u2318G)",
1981
- "aria-label": "Toggle grid overlay",
1982
- children: /* @__PURE__ */ jsx(GridIcon, { active: showGrid })
3434
+ d: "M2 2L14 14M2 14L14 2",
3435
+ stroke: "currentColor",
3436
+ strokeWidth: "2",
3437
+ strokeLinecap: "round"
1983
3438
  }
1984
- ) })
3439
+ )
1985
3440
  }
1986
3441
  ),
1987
- /* @__PURE__ */ jsx(
1988
- "button",
1989
- {
1990
- type: "button",
1991
- onMouseDown: handleBarMouseDown,
1992
- onTouchStart: handleBarTouchStart,
1993
- onClick: handleBarClick,
1994
- className: `
1995
- w-32 h-4 bg-gray-50 rounded-full transition-opacity
1996
- ${isDragging ? "opacity-100 cursor-grabbing" : "opacity-60 hover:opacity-100 cursor-grab"}
1997
- `,
1998
- "aria-label": isExpanded ? "Close dev tools" : "Open dev tools"
1999
- }
2000
- )
2001
- ]
2002
- }
2003
- )
3442
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
3443
+ ] }),
3444
+ title && /* @__PURE__ */ jsx(DialogTitle, { children: title }),
3445
+ description && /* @__PURE__ */ jsx(DialogDescription, { children: description }),
3446
+ /* @__PURE__ */ jsx(DialogBody, { children })
3447
+ ] })
3448
+ ] })
3449
+ ]
3450
+ }
3451
+ );
3452
+ };
3453
+ var DialogParts = Object.assign(DialogRoot, {
3454
+ Root: DialogRoot,
3455
+ Trigger: DialogTrigger,
3456
+ Portal: DialogPortal,
3457
+ Backdrop: DialogBackdrop,
3458
+ Popup: DialogPopup,
3459
+ Title: DialogTitle,
3460
+ Description: DialogDescription,
3461
+ Close: DialogClose,
3462
+ Body: DialogBody,
3463
+ Footer: DialogFooter
3464
+ });
3465
+ var videoDialogVariants = tv({
3466
+ base: [
3467
+ // Fixed positioning covering viewport
3468
+ "fixed inset-0",
3469
+ // Dark background base
3470
+ "bg-black",
3471
+ // Flex centering for the video
3472
+ "flex items-center justify-center",
3473
+ // Animation
3474
+ "transition-opacity duration-300",
3475
+ "data-[starting-style]:opacity-0",
3476
+ "data-[ending-style]:opacity-0",
3477
+ // Focus outline
3478
+ "outline-none"
3479
+ ]
3480
+ });
3481
+ var closeButtonVariants = tv({
3482
+ base: [
3483
+ // Positioning
3484
+ "absolute z-50",
3485
+ // Size and shape
3486
+ "w-48 h-48 rounded-full",
3487
+ // Colors
3488
+ "bg-black/60 text-white",
3489
+ "hover:bg-black/80",
3490
+ // Transition
3491
+ "transition-all duration-150",
3492
+ // Focus
3493
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50",
3494
+ // Flex centering for icon
3495
+ "flex items-center justify-center",
3496
+ // Cursor
3497
+ "cursor-pointer"
3498
+ ],
3499
+ variants: {
3500
+ position: {
3501
+ "top-right": "top-24 right-24",
3502
+ "top-left": "top-24 left-24"
3503
+ }
3504
+ },
3505
+ defaultVariants: {
3506
+ position: "top-right"
3507
+ }
3508
+ });
3509
+ var videoContainerVariants = tv({
3510
+ base: [
3511
+ // Relative for z-index
3512
+ "relative z-10",
3513
+ // Fill available space
3514
+ "w-full h-full",
3515
+ // Flex to center the video
3516
+ "flex items-center justify-center",
3517
+ // Padding from viewport edges
3518
+ "p-16 sm:p-24 lg:p-32"
3519
+ ]
3520
+ });
3521
+ var VideoDialog = React14.forwardRef(
3522
+ ({
3523
+ trigger,
3524
+ src,
3525
+ cloudflare,
3526
+ blur = "high",
3527
+ overlay = "vignette",
3528
+ backdropOpacity = 0.6,
3529
+ showClose = true,
3530
+ closePosition = "top-right",
3531
+ rounded = "lg",
3532
+ open: controlledOpen,
3533
+ defaultOpen,
3534
+ onOpenChange,
3535
+ className,
3536
+ autoPlay,
3537
+ ...videoProps
3538
+ }, ref) => {
3539
+ const [internalOpen, setInternalOpen] = React14.useState(
3540
+ defaultOpen ?? false
3541
+ );
3542
+ const isControlled = controlledOpen !== void 0;
3543
+ const open = isControlled ? controlledOpen : internalOpen;
3544
+ const handleOpenChange = React14.useCallback(
3545
+ (newOpen) => {
3546
+ if (!isControlled) {
3547
+ setInternalOpen(newOpen);
3548
+ }
3549
+ onOpenChange?.(newOpen);
3550
+ },
3551
+ [isControlled, onOpenChange]
3552
+ );
3553
+ const primaryVideoRef = React14.useRef(null);
3554
+ return /* @__PURE__ */ jsxs(
3555
+ Dialog$1.Root,
3556
+ {
3557
+ open,
3558
+ defaultOpen,
3559
+ onOpenChange: handleOpenChange,
3560
+ children: [
3561
+ /* @__PURE__ */ jsx(
3562
+ Dialog$1.Trigger,
3563
+ {
3564
+ render: React14.isValidElement(trigger) ? trigger : void 0,
3565
+ children: !React14.isValidElement(trigger) ? trigger : void 0
3566
+ }
3567
+ ),
3568
+ /* @__PURE__ */ jsx(Dialog$1.Portal, { children: /* @__PURE__ */ jsxs(
3569
+ Dialog$1.Popup,
3570
+ {
3571
+ ref,
3572
+ className: cn(videoDialogVariants(), className),
3573
+ "data-component": "video-dialog",
3574
+ children: [
3575
+ /* @__PURE__ */ jsx(
3576
+ BlurredVideoBackdrop,
3577
+ {
3578
+ videoRef: primaryVideoRef,
3579
+ blur,
3580
+ overlay,
3581
+ opacity: backdropOpacity,
3582
+ extension: 120
3583
+ }
3584
+ ),
3585
+ showClose && /* @__PURE__ */ jsxs(
3586
+ Dialog$1.Close,
3587
+ {
3588
+ className: closeButtonVariants({ position: closePosition }),
3589
+ children: [
3590
+ /* @__PURE__ */ jsx(
3591
+ "svg",
3592
+ {
3593
+ width: "20",
3594
+ height: "20",
3595
+ viewBox: "0 0 20 20",
3596
+ fill: "none",
3597
+ "aria-hidden": "true",
3598
+ children: /* @__PURE__ */ jsx(
3599
+ "path",
3600
+ {
3601
+ d: "M4 4L16 16M4 16L16 4",
3602
+ stroke: "currentColor",
3603
+ strokeWidth: "2",
3604
+ strokeLinecap: "round"
3605
+ }
3606
+ )
3607
+ }
3608
+ ),
3609
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
3610
+ ]
3611
+ }
3612
+ ),
3613
+ /* @__PURE__ */ jsx("div", { className: videoContainerVariants(), children: /* @__PURE__ */ jsx(
3614
+ VideoPlayer,
3615
+ {
3616
+ src,
3617
+ cloudflare,
3618
+ videoRef: primaryVideoRef,
3619
+ rounded,
3620
+ autoPlay: autoPlay ?? open,
3621
+ aspectRatio: "16/9",
3622
+ style: {
3623
+ width: "min(100%, calc((100vh - 64px) * 16 / 9))",
3624
+ maxHeight: "calc(100vh - 64px)"
3625
+ },
3626
+ ...videoProps
3627
+ }
3628
+ ) })
3629
+ ]
3630
+ }
3631
+ ) })
3632
+ ]
2004
3633
  }
2005
- )
2006
- ] });
3634
+ );
3635
+ }
3636
+ );
3637
+ VideoDialog.displayName = "VideoDialog";
3638
+ var VideoWithBackdropContext = React14.createContext(null);
3639
+ function useVideoWithBackdropContext() {
3640
+ const context = React14.useContext(VideoWithBackdropContext);
3641
+ if (!context) {
3642
+ throw new Error(
3643
+ "VideoWithBackdrop compound components must be used within VideoWithBackdrop.Root"
3644
+ );
3645
+ }
3646
+ return context;
2007
3647
  }
3648
+ var videoWithBackdropVariants = tv({
3649
+ base: ["relative", "overflow-hidden", "bg-black"],
3650
+ variants: {
3651
+ /**
3652
+ * Full-height mode for dialogs.
3653
+ */
3654
+ fullHeight: {
3655
+ true: "h-full w-full",
3656
+ false: ""
3657
+ }
3658
+ },
3659
+ defaultVariants: {
3660
+ fullHeight: false
3661
+ }
3662
+ });
3663
+ var contentVariants = tv({
3664
+ base: ["relative", "z-10", "flex", "items-center", "justify-center"],
3665
+ variants: {
3666
+ fullHeight: {
3667
+ true: "h-full w-full",
3668
+ false: ""
3669
+ },
3670
+ padding: {
3671
+ none: "",
3672
+ sm: "p-16",
3673
+ md: "p-24",
3674
+ lg: "p-48"
3675
+ }
3676
+ },
3677
+ defaultVariants: {
3678
+ fullHeight: false,
3679
+ padding: "md"
3680
+ }
3681
+ });
3682
+ var VideoWithBackdropRoot = React14.forwardRef(({ className, src, cloudflare, fullHeight, children, ...props }, ref) => {
3683
+ const videoRef = React14.useRef(null);
3684
+ const contextValue = React14.useMemo(
3685
+ () => ({ videoRef, src, cloudflare }),
3686
+ [src, cloudflare]
3687
+ );
3688
+ return /* @__PURE__ */ jsx(VideoWithBackdropContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
3689
+ "div",
3690
+ {
3691
+ ref,
3692
+ className: cn(videoWithBackdropVariants({ fullHeight }), className),
3693
+ "data-full-height": fullHeight ?? false,
3694
+ ...props,
3695
+ children
3696
+ }
3697
+ ) });
3698
+ });
3699
+ VideoWithBackdropRoot.displayName = "VideoWithBackdropRoot";
3700
+ var VideoWithBackdropBackdrop = React14.forwardRef(({ ...props }, ref) => {
3701
+ const { videoRef } = useVideoWithBackdropContext();
3702
+ return /* @__PURE__ */ jsx(BlurredVideoBackdrop, { ref, videoRef, ...props });
3703
+ });
3704
+ VideoWithBackdropBackdrop.displayName = "VideoWithBackdropBackdrop";
3705
+ var VideoWithBackdropContent = React14.forwardRef(({ className, fullHeight, padding, children, ...props }, ref) => {
3706
+ return /* @__PURE__ */ jsx(
3707
+ "div",
3708
+ {
3709
+ ref,
3710
+ className: cn(contentVariants({ fullHeight, padding }), className),
3711
+ ...props,
3712
+ children
3713
+ }
3714
+ );
3715
+ });
3716
+ VideoWithBackdropContent.displayName = "VideoWithBackdropContent";
3717
+ var VideoWithBackdropVideo = React14.forwardRef(({ className, maxWidth = "960px", cloudflare, src, ...props }, ref) => {
3718
+ const context = useVideoWithBackdropContext();
3719
+ const videoCloudflare = cloudflare ?? context.cloudflare;
3720
+ const videoSrc = src ?? context.src;
3721
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("w-full", className), style: { maxWidth }, children: /* @__PURE__ */ jsx(
3722
+ VideoPlayer,
3723
+ {
3724
+ cloudflare: videoCloudflare,
3725
+ src: videoSrc,
3726
+ videoRef: context.videoRef,
3727
+ ...props
3728
+ }
3729
+ ) });
3730
+ });
3731
+ VideoWithBackdropVideo.displayName = "VideoWithBackdropVideo";
3732
+ var VideoWithBackdrop = React14.forwardRef(
3733
+ ({
3734
+ src,
3735
+ cloudflare,
3736
+ blur = "high",
3737
+ overlay = "vignette",
3738
+ backdropOpacity = 0.6,
3739
+ maxWidth = "960px",
3740
+ padding = "md",
3741
+ rounded = "lg",
3742
+ className,
3743
+ targetFps = 30,
3744
+ scale = 0.5,
3745
+ ...videoProps
3746
+ }, ref) => {
3747
+ const videoRef = React14.useRef(null);
3748
+ return /* @__PURE__ */ jsxs(
3749
+ "div",
3750
+ {
3751
+ ref,
3752
+ className: cn(
3753
+ videoWithBackdropVariants({ fullHeight: true }),
3754
+ className
3755
+ ),
3756
+ "data-component": "video-with-backdrop",
3757
+ children: [
3758
+ /* @__PURE__ */ jsx(
3759
+ BlurredVideoBackdrop,
3760
+ {
3761
+ videoRef,
3762
+ blur,
3763
+ overlay,
3764
+ opacity: backdropOpacity,
3765
+ targetFps,
3766
+ scale
3767
+ }
3768
+ ),
3769
+ /* @__PURE__ */ jsx("div", { className: cn(contentVariants({ fullHeight: true, padding })), children: /* @__PURE__ */ jsx("div", { className: "w-full", style: { maxWidth }, children: /* @__PURE__ */ jsx(
3770
+ VideoPlayer,
3771
+ {
3772
+ src,
3773
+ cloudflare,
3774
+ videoRef,
3775
+ rounded,
3776
+ ...videoProps
3777
+ }
3778
+ ) }) })
3779
+ ]
3780
+ }
3781
+ );
3782
+ }
3783
+ );
3784
+ VideoWithBackdrop.displayName = "VideoWithBackdrop";
3785
+ var VideoWithBackdropParts = Object.assign(VideoWithBackdropRoot, {
3786
+ Root: VideoWithBackdropRoot,
3787
+ Backdrop: VideoWithBackdropBackdrop,
3788
+ Content: VideoWithBackdropContent,
3789
+ Video: VideoWithBackdropVideo
3790
+ });
2008
3791
  var cardVariants = tv({
2009
3792
  base: "relative flex overflow-hidden rounded-surface-card bg-card-background stroke-surface-card border-border-subtle border-solid",
2010
3793
  variants: {
@@ -2022,7 +3805,7 @@ var cardVariants = tv({
2022
3805
  layout: "vertical"
2023
3806
  }
2024
3807
  });
2025
- var Card = React11.forwardRef(
3808
+ var Card = React14.forwardRef(
2026
3809
  ({ className, layout, ...props }, ref) => {
2027
3810
  return /* @__PURE__ */ jsx(
2028
3811
  "div",
@@ -2044,7 +3827,7 @@ var cardImageVariants = tv({
2044
3827
  "[.flex-row>&]:aspect-auto [.flex-row>&]:w-2/5 [.flex-row>&]:self-stretch"
2045
3828
  ]
2046
3829
  });
2047
- var CardImage = React11.forwardRef(
3830
+ var CardImage = React14.forwardRef(
2048
3831
  ({ className, src, alt = "", ...props }, ref) => {
2049
3832
  return /* @__PURE__ */ jsx(
2050
3833
  "div",
@@ -2079,7 +3862,7 @@ var cardContentVariants = tv({
2079
3862
  }
2080
3863
  }
2081
3864
  });
2082
- var CardContent = React11.forwardRef(
3865
+ var CardContent = React14.forwardRef(
2083
3866
  ({ className, justify, ...props }, ref) => {
2084
3867
  return /* @__PURE__ */ jsx(
2085
3868
  "div",
@@ -2095,7 +3878,7 @@ CardContent.displayName = "CardContent";
2095
3878
  var cardEyebrowVariants = tv({
2096
3879
  base: "typography-overline text-text-muted uppercase tracking-wider"
2097
3880
  });
2098
- var CardEyebrow = React11.forwardRef(
3881
+ var CardEyebrow = React14.forwardRef(
2099
3882
  ({ className, ...props }, ref) => {
2100
3883
  return /* @__PURE__ */ jsx(
2101
3884
  "p",
@@ -2111,7 +3894,7 @@ CardEyebrow.displayName = "CardEyebrow";
2111
3894
  var cardTitleVariants = tv({
2112
3895
  base: "typography-h5 text-text-primary"
2113
3896
  });
2114
- var CardTitle = React11.forwardRef(
3897
+ var CardTitle = React14.forwardRef(
2115
3898
  ({ className, as: Component = "h3", ...props }, ref) => {
2116
3899
  return /* @__PURE__ */ jsx(
2117
3900
  Component,
@@ -2127,7 +3910,7 @@ CardTitle.displayName = "CardTitle";
2127
3910
  var cardDescriptionVariants = tv({
2128
3911
  base: "typography-body-small text-text-secondary"
2129
3912
  });
2130
- var CardDescription = React11.forwardRef(({ className, ...props }, ref) => {
3913
+ var CardDescription = React14.forwardRef(({ className, ...props }, ref) => {
2131
3914
  return /* @__PURE__ */ jsx(
2132
3915
  "p",
2133
3916
  {
@@ -2141,7 +3924,7 @@ CardDescription.displayName = "CardDescription";
2141
3924
  var cardBodyVariants = tv({
2142
3925
  base: "flex w-full flex-col gap-spatial-card-small-gap"
2143
3926
  });
2144
- var CardBody = React11.forwardRef(
3927
+ var CardBody = React14.forwardRef(
2145
3928
  ({ className, ...props }, ref) => {
2146
3929
  return /* @__PURE__ */ jsx(
2147
3930
  "div",
@@ -2157,7 +3940,7 @@ CardBody.displayName = "CardBody";
2157
3940
  var cardActionsVariants = tv({
2158
3941
  base: "flex gap-12"
2159
3942
  });
2160
- var CardActions = React11.forwardRef(
3943
+ var CardActions = React14.forwardRef(
2161
3944
  ({ className, ...props }, ref) => {
2162
3945
  return /* @__PURE__ */ jsx(
2163
3946
  "div",
@@ -2170,16 +3953,16 @@ var CardActions = React11.forwardRef(
2170
3953
  }
2171
3954
  );
2172
3955
  CardActions.displayName = "CardActions";
2173
- var NavbarContext = React11.createContext({
3956
+ var NavbarContext = React14.createContext({
2174
3957
  isMobileMenuOpen: false,
2175
3958
  setIsMobileMenuOpen: () => {
2176
3959
  }
2177
3960
  });
2178
- var Navbar = React11.forwardRef(
3961
+ var Navbar = React14.forwardRef(
2179
3962
  ({ className, children, ...props }, ref) => {
2180
- const [isMobileMenuOpen, setIsMobileMenuOpen] = React11.useState(false);
2181
- const navRef = React11.useRef(null);
2182
- React11.useEffect(() => {
3963
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = React14.useState(false);
3964
+ const navRef = React14.useRef(null);
3965
+ React14.useEffect(() => {
2183
3966
  const updateHeight = () => {
2184
3967
  if (navRef.current) {
2185
3968
  const height = navRef.current.offsetHeight;
@@ -2193,7 +3976,7 @@ var Navbar = React11.forwardRef(
2193
3976
  window.addEventListener("resize", updateHeight);
2194
3977
  return () => window.removeEventListener("resize", updateHeight);
2195
3978
  }, []);
2196
- const mergedRef = React11.useCallback(
3979
+ const mergedRef = React14.useCallback(
2197
3980
  (node) => {
2198
3981
  navRef.current = node;
2199
3982
  if (typeof ref === "function") {
@@ -2230,14 +4013,14 @@ var Navbar = React11.forwardRef(
2230
4013
  }
2231
4014
  );
2232
4015
  Navbar.displayName = "Navbar";
2233
- var NavbarBrand = React11.forwardRef(
4016
+ var NavbarBrand = React14.forwardRef(
2234
4017
  ({ className, asChild = false, ...props }, ref) => {
2235
4018
  const Comp = asChild ? Slot : "div";
2236
4019
  return /* @__PURE__ */ jsx(Comp, { ref, className: cn("shrink-0", className), ...props });
2237
4020
  }
2238
4021
  );
2239
4022
  NavbarBrand.displayName = "NavbarBrand";
2240
- var NavbarLinks = React11.forwardRef(
4023
+ var NavbarLinks = React14.forwardRef(
2241
4024
  ({ className, ...props }, ref) => {
2242
4025
  return /* @__PURE__ */ jsx(
2243
4026
  "div",
@@ -2253,7 +4036,7 @@ var NavbarLinks = React11.forwardRef(
2253
4036
  }
2254
4037
  );
2255
4038
  NavbarLinks.displayName = "NavbarLinks";
2256
- var NavbarLink = React11.forwardRef(
4039
+ var NavbarLink = React14.forwardRef(
2257
4040
  ({ className, asChild = false, active, ...props }, ref) => {
2258
4041
  const Comp = asChild ? Slot : "a";
2259
4042
  return /* @__PURE__ */ jsx(
@@ -2271,7 +4054,7 @@ var NavbarLink = React11.forwardRef(
2271
4054
  }
2272
4055
  );
2273
4056
  NavbarLink.displayName = "NavbarLink";
2274
- var NavbarActions = React11.forwardRef(
4057
+ var NavbarActions = React14.forwardRef(
2275
4058
  ({ className, ...props }, ref) => {
2276
4059
  return /* @__PURE__ */ jsx(
2277
4060
  "div",
@@ -2287,10 +4070,10 @@ var NavbarActions = React11.forwardRef(
2287
4070
  }
2288
4071
  );
2289
4072
  NavbarActions.displayName = "NavbarActions";
2290
- var NavbarMobileMenu = React11.forwardRef(({ className, children, ...props }, ref) => {
2291
- const { isMobileMenuOpen, setIsMobileMenuOpen } = React11.useContext(NavbarContext);
2292
- return /* @__PURE__ */ jsx(Dialog.Root, { open: isMobileMenuOpen, onOpenChange: setIsMobileMenuOpen, children: /* @__PURE__ */ jsx(Dialog.Portal, { children: /* @__PURE__ */ jsxs(
2293
- Dialog.Popup,
4073
+ var NavbarMobileMenu = React14.forwardRef(({ className, children, ...props }, ref) => {
4074
+ const { isMobileMenuOpen, setIsMobileMenuOpen } = React14.useContext(NavbarContext);
4075
+ return /* @__PURE__ */ jsx(Dialog$1.Root, { open: isMobileMenuOpen, onOpenChange: setIsMobileMenuOpen, children: /* @__PURE__ */ jsx(Dialog$1.Portal, { children: /* @__PURE__ */ jsxs(
4076
+ Dialog$1.Popup,
2294
4077
  {
2295
4078
  ref,
2296
4079
  className: cn(
@@ -2303,7 +4086,7 @@ var NavbarMobileMenu = React11.forwardRef(({ className, children, ...props }, re
2303
4086
  ),
2304
4087
  ...props,
2305
4088
  children: [
2306
- /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: "Navigation menu" }),
4089
+ /* @__PURE__ */ jsx(Dialog$1.Title, { className: "sr-only", children: "Navigation menu" }),
2307
4090
  /* @__PURE__ */ jsx(
2308
4091
  "div",
2309
4092
  {
@@ -2322,8 +4105,8 @@ var NavbarMobileMenu = React11.forwardRef(({ className, children, ...props }, re
2322
4105
  ) }) });
2323
4106
  });
2324
4107
  NavbarMobileMenu.displayName = "NavbarMobileMenu";
2325
- var NavbarMobileMenuButton = React11.forwardRef(({ className, asChild = false, children, ...props }, ref) => {
2326
- const { isMobileMenuOpen, setIsMobileMenuOpen } = React11.useContext(NavbarContext);
4108
+ var NavbarMobileMenuButton = React14.forwardRef(({ className, asChild = false, children, ...props }, ref) => {
4109
+ const { isMobileMenuOpen, setIsMobileMenuOpen } = React14.useContext(NavbarContext);
2327
4110
  const handleClick = () => {
2328
4111
  setIsMobileMenuOpen(!isMobileMenuOpen);
2329
4112
  };
@@ -2358,8 +4141,8 @@ var NavbarMobileMenuButton = React11.forwardRef(({ className, asChild = false, c
2358
4141
  );
2359
4142
  });
2360
4143
  NavbarMobileMenuButton.displayName = "NavbarMobileMenuButton";
2361
- var NavbarMobileMenuLink = React11.forwardRef(({ className, asChild = false, active, onClick, ...props }, ref) => {
2362
- const { setIsMobileMenuOpen } = React11.useContext(NavbarContext);
4144
+ var NavbarMobileMenuLink = React14.forwardRef(({ className, asChild = false, active, onClick, ...props }, ref) => {
4145
+ const { setIsMobileMenuOpen } = React14.useContext(NavbarContext);
2363
4146
  const Comp = asChild ? Slot : "a";
2364
4147
  const handleClick = (event) => {
2365
4148
  setIsMobileMenuOpen(false);
@@ -2405,7 +4188,7 @@ var usGovBannerVariants = tv({
2405
4188
  variant: "default"
2406
4189
  }
2407
4190
  });
2408
- var USGovBanner = React11.forwardRef(
4191
+ var USGovBanner = React14.forwardRef(
2409
4192
  ({
2410
4193
  className,
2411
4194
  variant,
@@ -2492,7 +4275,7 @@ var bannerVariants = tv({
2492
4275
  colorScheme: "light"
2493
4276
  }
2494
4277
  });
2495
- var Banner = React11.forwardRef(
4278
+ var Banner = React14.forwardRef(
2496
4279
  ({ className, colorScheme, heading, description, action, ...props }, ref) => {
2497
4280
  return /* @__PURE__ */ jsx(
2498
4281
  "section",
@@ -2559,7 +4342,7 @@ var cardGridVariants = tv({
2559
4342
  variant: "A"
2560
4343
  }
2561
4344
  });
2562
- var CardGrid = React11.forwardRef(
4345
+ var CardGrid = React14.forwardRef(
2563
4346
  ({ className, variant, title, cards, ...props }, ref) => {
2564
4347
  return /* @__PURE__ */ jsxs(
2565
4348
  "section",
@@ -2592,7 +4375,7 @@ var CardGrid = React11.forwardRef(
2592
4375
  // Desktop: 3 columns for variant A, 2 columns for variant B
2593
4376
  variant === "A" && "lg:grid-cols-3"
2594
4377
  ),
2595
- children: React11.Children.toArray(cards).map((card) => /* @__PURE__ */ jsx("div", { children: card }, card.key))
4378
+ children: React14.Children.toArray(cards).map((card) => /* @__PURE__ */ jsx("div", { children: card }, card.key))
2596
4379
  }
2597
4380
  )
2598
4381
  ]
@@ -2627,7 +4410,7 @@ var twoColumnSectionVariants = tv({
2627
4410
  layout: "asymmetric"
2628
4411
  }
2629
4412
  });
2630
- var TwoColumnSection = React11.forwardRef(
4413
+ var TwoColumnSection = React14.forwardRef(
2631
4414
  ({
2632
4415
  className,
2633
4416
  colorScheme = "dark",
@@ -2709,7 +4492,7 @@ var TwoColumnSection = React11.forwardRef(
2709
4492
  }
2710
4493
  );
2711
4494
  TwoColumnSection.displayName = "TwoColumnSection";
2712
- var FaqSection = React11.forwardRef(
4495
+ var FaqSection = React14.forwardRef(
2713
4496
  ({
2714
4497
  className,
2715
4498
  colorScheme = "light",
@@ -2799,7 +4582,7 @@ var heroContentVariants = tv({
2799
4582
  "lg:p-72"
2800
4583
  ]
2801
4584
  });
2802
- var HeroHeader = React11.forwardRef(
4585
+ var HeroHeader = React14.forwardRef(
2803
4586
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2804
4587
  "div",
2805
4588
  {
@@ -2810,7 +4593,7 @@ var HeroHeader = React11.forwardRef(
2810
4593
  )
2811
4594
  );
2812
4595
  HeroHeader.displayName = "Hero.Header";
2813
- var HeroContent = React11.forwardRef(
4596
+ var HeroContent = React14.forwardRef(
2814
4597
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2815
4598
  "div",
2816
4599
  {
@@ -2824,7 +4607,7 @@ HeroContent.displayName = "Hero.Content";
2824
4607
  function isColorString(background) {
2825
4608
  return typeof background === "string" && (background.startsWith("#") || background.startsWith("rgb") || background.startsWith("hsl") || /^(var\(|[a-z]+$)/i.test(background));
2826
4609
  }
2827
- var Hero = React11.forwardRef(
4610
+ var Hero = React14.forwardRef(
2828
4611
  ({
2829
4612
  className,
2830
4613
  children,
@@ -2885,7 +4668,7 @@ var Hero = React11.forwardRef(
2885
4668
  Hero.displayName = "Hero";
2886
4669
  Hero.Header = HeroHeader;
2887
4670
  Hero.Content = HeroContent;
2888
- var Prose = React11.forwardRef(
4671
+ var Prose = React14.forwardRef(
2889
4672
  ({ className, children, ...props }, ref) => {
2890
4673
  return /* @__PURE__ */ jsx(
2891
4674
  "div",
@@ -2904,7 +4687,7 @@ var Prose = React11.forwardRef(
2904
4687
  }
2905
4688
  );
2906
4689
  Prose.displayName = "Prose";
2907
- var ProseSection = React11.forwardRef(
4690
+ var ProseSection = React14.forwardRef(
2908
4691
  ({ className, heading, as = "h2", children, ...props }, ref) => {
2909
4692
  const Heading = as;
2910
4693
  const headingClass = as === "h2" ? "typography-h3" : "typography-h4";
@@ -2973,7 +4756,7 @@ var quoteBlockVariants = tv({
2973
4756
  size: "default"
2974
4757
  }
2975
4758
  });
2976
- var QuoteBlock = React11.forwardRef(
4759
+ var QuoteBlock = React14.forwardRef(
2977
4760
  ({
2978
4761
  className,
2979
4762
  quote,
@@ -3071,7 +4854,7 @@ var riverVariants = tv({
3071
4854
  variant: "A"
3072
4855
  }
3073
4856
  });
3074
- var River = React11.forwardRef(
4857
+ var River = React14.forwardRef(
3075
4858
  ({
3076
4859
  className,
3077
4860
  variant,
@@ -3168,7 +4951,7 @@ var toutVariants = tv({
3168
4951
  align: "left"
3169
4952
  }
3170
4953
  });
3171
- var Tout = React11.forwardRef(
4954
+ var Tout = React14.forwardRef(
3172
4955
  ({
3173
4956
  className,
3174
4957
  colorScheme = "light",
@@ -3316,6 +5099,90 @@ var Tout = React11.forwardRef(
3316
5099
  }
3317
5100
  );
3318
5101
  Tout.displayName = "Tout";
5102
+ var BREAKPOINTS = {
5103
+ sm: 320,
5104
+ md: 768,
5105
+ lg: 1440
5106
+ };
5107
+ function getCurrentBreakpoint(width) {
5108
+ if (width >= BREAKPOINTS.lg) return "lg";
5109
+ if (width >= BREAKPOINTS.md) return "md";
5110
+ return "sm";
5111
+ }
5112
+ function useBreakpoint() {
5113
+ const [breakpoint, setBreakpoint] = React14.useState(() => {
5114
+ if (typeof window === "undefined") return "sm";
5115
+ return getCurrentBreakpoint(window.innerWidth);
5116
+ });
5117
+ React14.useEffect(() => {
5118
+ const handleResize = () => {
5119
+ setBreakpoint(getCurrentBreakpoint(window.innerWidth));
5120
+ };
5121
+ handleResize();
5122
+ window.addEventListener("resize", handleResize);
5123
+ return () => window.removeEventListener("resize", handleResize);
5124
+ }, []);
5125
+ return breakpoint;
5126
+ }
5127
+ function useMinBreakpoint(breakpoint) {
5128
+ const [matches, setMatches] = React14.useState(() => {
5129
+ if (typeof window === "undefined") return false;
5130
+ return window.innerWidth >= BREAKPOINTS[breakpoint];
5131
+ });
5132
+ React14.useEffect(() => {
5133
+ const mediaQuery = window.matchMedia(
5134
+ `(min-width: ${BREAKPOINTS[breakpoint]}px)`
5135
+ );
5136
+ setMatches(mediaQuery.matches);
5137
+ const handleChange = (event) => {
5138
+ setMatches(event.matches);
5139
+ };
5140
+ mediaQuery.addEventListener("change", handleChange);
5141
+ return () => mediaQuery.removeEventListener("change", handleChange);
5142
+ }, [breakpoint]);
5143
+ return matches;
5144
+ }
5145
+ function useMaxBreakpoint(breakpoint) {
5146
+ const [matches, setMatches] = React14.useState(() => {
5147
+ if (typeof window === "undefined") return false;
5148
+ return window.innerWidth < BREAKPOINTS[breakpoint];
5149
+ });
5150
+ React14.useEffect(() => {
5151
+ const mediaQuery = window.matchMedia(
5152
+ `(max-width: ${BREAKPOINTS[breakpoint] - 1}px)`
5153
+ );
5154
+ setMatches(mediaQuery.matches);
5155
+ const handleChange = (event) => {
5156
+ setMatches(event.matches);
5157
+ };
5158
+ mediaQuery.addEventListener("change", handleChange);
5159
+ return () => mediaQuery.removeEventListener("change", handleChange);
5160
+ }, [breakpoint]);
5161
+ return matches;
5162
+ }
5163
+ function useEventListener(eventName, handler, element, options) {
5164
+ const savedHandler = React14.useRef(handler);
5165
+ React14.useLayoutEffect(() => {
5166
+ savedHandler.current = handler;
5167
+ }, [handler]);
5168
+ React14.useEffect(() => {
5169
+ const targetElement = element ?? window;
5170
+ if (!targetElement?.addEventListener) {
5171
+ return;
5172
+ }
5173
+ const eventListener = (event) => {
5174
+ savedHandler.current(event);
5175
+ };
5176
+ targetElement.addEventListener(eventName, eventListener, options);
5177
+ return () => {
5178
+ targetElement.removeEventListener(
5179
+ eventName,
5180
+ eventListener,
5181
+ options
5182
+ );
5183
+ };
5184
+ }, [eventName, element, options]);
5185
+ }
3319
5186
 
3320
5187
  // ../tokens/dist/collections/types.js
3321
5188
  function isColorValue(value) {
@@ -3592,6 +5459,70 @@ var baseColorTokens = {
3592
5459
  $type: "color",
3593
5460
  $value: "{primitive.color.blue.v250}"
3594
5461
  }
5462
+ },
5463
+ // Video Player tokens (color-video-player-*)
5464
+ // Used for fullscreen video modal, controls, and captions
5465
+ "video-player": {
5466
+ "controls-bg": {
5467
+ $type: "color",
5468
+ $value: "{primitive.color.alpha-black.40}",
5469
+ $description: "Video controls bar background (glassmorphic)"
5470
+ },
5471
+ "controls-text": {
5472
+ $type: "color",
5473
+ $value: "{primitive.color.white}",
5474
+ $description: "Video controls text and icons"
5475
+ },
5476
+ "controls-hover": {
5477
+ $type: "color",
5478
+ $value: "{primitive.color.alpha-white.20}",
5479
+ $description: "Video controls hover state"
5480
+ },
5481
+ "button-bg": {
5482
+ $type: "color",
5483
+ $value: "{primitive.color.alpha-white.10}",
5484
+ $description: "Control button background (visible on dark video)"
5485
+ },
5486
+ "button-bg-hover": {
5487
+ $type: "color",
5488
+ $value: "{primitive.color.alpha-white.20}",
5489
+ $description: "Control button hover background"
5490
+ },
5491
+ "button-bg-active": {
5492
+ $type: "color",
5493
+ $value: "{primitive.color.alpha-white.30}",
5494
+ $description: "Control button active/pressed background"
5495
+ },
5496
+ "caption-bg": {
5497
+ $type: "color",
5498
+ $value: "{primitive.color.alpha-black.70}",
5499
+ $description: "Caption background overlay"
5500
+ },
5501
+ "caption-text": {
5502
+ $type: "color",
5503
+ $value: "{primitive.color.white}",
5504
+ $description: "Caption text color"
5505
+ },
5506
+ "backdrop-overlay": {
5507
+ $type: "color",
5508
+ $value: "{primitive.color.alpha-black.90}",
5509
+ $description: "Modal backdrop overlay"
5510
+ },
5511
+ "progress-bg": {
5512
+ $type: "color",
5513
+ $value: "{primitive.color.alpha-white.30}",
5514
+ $description: "Progress bar track background"
5515
+ },
5516
+ "progress-fill": {
5517
+ $type: "color",
5518
+ $value: "{primitive.color.white}",
5519
+ $description: "Progress bar fill color"
5520
+ },
5521
+ "tooltip-bg": {
5522
+ $type: "color",
5523
+ $value: "{primitive.color.alpha-black.90}",
5524
+ $description: "Video tooltip background"
5525
+ }
3595
5526
  }
3596
5527
  }
3597
5528
  }
@@ -6123,6 +8054,59 @@ var baseSpatialTokens = {
6123
8054
  $description: "Gap in mobile menu items"
6124
8055
  }
6125
8056
  }
8057
+ },
8058
+ /**
8059
+ * Video Player Spacing Tokens
8060
+ *
8061
+ * Spacing for video player controls, captions, and overlays.
8062
+ */
8063
+ "video-player": {
8064
+ controls: {
8065
+ height: {
8066
+ $type: "dimension",
8067
+ $value: "{primitive.spacing.48}",
8068
+ $description: "Height of video player controls bar"
8069
+ },
8070
+ padding: {
8071
+ $type: "dimension",
8072
+ $value: "{primitive.spacing.16}",
8073
+ $description: "Padding inside controls bar"
8074
+ },
8075
+ gap: {
8076
+ $type: "dimension",
8077
+ $value: "{primitive.spacing.12}",
8078
+ $description: "Gap between control buttons"
8079
+ }
8080
+ },
8081
+ caption: {
8082
+ "padding-x": {
8083
+ $type: "dimension",
8084
+ $value: "{primitive.spacing.16}",
8085
+ $description: "Horizontal padding for caption text"
8086
+ },
8087
+ "padding-y": {
8088
+ $type: "dimension",
8089
+ $value: "{primitive.spacing.8}",
8090
+ $description: "Vertical padding for caption text"
8091
+ },
8092
+ "offset-bottom": {
8093
+ $type: "dimension",
8094
+ $value: "{primitive.spacing.64}",
8095
+ $description: "Distance from bottom of video to caption"
8096
+ }
8097
+ },
8098
+ "close-button": {
8099
+ size: {
8100
+ $type: "dimension",
8101
+ $value: "{primitive.spacing.40}",
8102
+ $description: "Size of close button"
8103
+ },
8104
+ offset: {
8105
+ $type: "dimension",
8106
+ $value: "{primitive.spacing.16}",
8107
+ $description: "Offset from top-right corner"
8108
+ }
8109
+ }
6126
8110
  }
6127
8111
  },
6128
8112
  /**
@@ -7286,6 +9270,6 @@ function filterCSSVars(cssVars, prefix) {
7286
9270
  return result;
7287
9271
  }
7288
9272
 
7289
- export { Accordion, AccordionItem, BackgroundCompound as Background, BackgroundGradient, BackgroundImage, BackgroundOverlay, BackgroundStream, BackgroundVideo, Banner, Button, Card, CardActions, CardBody, CardContent, CardDescription, CardEyebrow, CardGrid, CardImage, CardTitle, DEFAULT_TITLE_TYPOGRAPHY, DevToolbar, FONT_SIZES, FaqSection, GridOverlay, Hero, BackgroundCompound as HeroBackground, BackgroundImage as HeroBackgroundImage, BackgroundStream as HeroBackgroundStream, BackgroundVideo as HeroBackgroundVideo, HeroContent, BackgroundGradient as HeroGradient, HeroHeader, BackgroundOverlay as HeroOverlay, IconButton, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Navbar, NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarMobileMenu, NavbarMobileMenuButton, NavbarMobileMenuLink, NdstudioFooter, PagerControl, Popover, PopoverArrow, PopoverBackdrop, PopoverClose, PopoverDescription, PopoverParts, PopoverPopup, PopoverPortal, PopoverPositioner, PopoverRoot, PopoverTitle, PopoverTrigger, Prose, ProseSection, QuoteBlock, River, Select, SelectGroup, SelectGroupLabel, SelectOption, SelectPopup, SelectRoot, SelectTrigger, ThemeProvider, Tooltip, TooltipArrow, TooltipParts, TooltipPopup, TooltipPortal, TooltipPositioner, TooltipProvider, TooltipRoot, TooltipTrigger, Tout, TwoColumnSection, USGovBanner, applyTheme, backgroundGradientVariants, backgroundImageVariants, backgroundOverlayVariants, backgroundStreamVariants, backgroundVariants, backgroundVideoVariants, bannerVariants, buttonThemeToStyleVars, buttonVariants, cardGridVariants, cardVariants, cn, createThemeStyle, filterCSSVars, fontSizeToClass, getToken, heroContentVariants, heroHeaderVariants, heroVariants, iconButtonVariants, inputGroupAddonVariants, inputGroupVariants, inputVariants, mergeCSSVars, pagerControlVariants, popoverArrowVariants, popoverPopupVariants, quoteBlockVariants, removeTheme, responsiveTypographyClass, riverVariants, selectOptionVariants, selectPopupVariants, selectTriggerVariants, themeToStyleVars, toCSSVars, tooltipArrowVariants, tooltipPopupVariants, twoColumnSectionVariants, useCSSVars, useTheme, useThemeTokens };
9273
+ export { Accordion, AccordionItem, BLUR_AMOUNTS, BREAKPOINTS, BackgroundCompound as Background, BackgroundGradient, BackgroundImage, BackgroundOverlay, BackgroundStream, BackgroundVideo, Banner, BlurredVideoBackdrop, Button, CaptionOverlay, Card, CardActions, CardBody, CardContent, CardDescription, CardEyebrow, CardGrid, CardImage, CardTitle, DEFAULT_TITLE_TYPOGRAPHY, DevToolbar, Dialog, DialogBackdrop, DialogBody, DialogClose, DialogDescription, DialogFooter, DialogParts, DialogPopup, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, FONT_SIZES, FaqSection, GridOverlay, Hero, BackgroundCompound as HeroBackground, BackgroundImage as HeroBackgroundImage, BackgroundStream as HeroBackgroundStream, BackgroundVideo as HeroBackgroundVideo, HeroContent, BackgroundGradient as HeroGradient, HeroHeader, BackgroundOverlay as HeroOverlay, IconButton, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Navbar, NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarMobileMenu, NavbarMobileMenuButton, NavbarMobileMenuLink, NdstudioFooter, PagerControl, Popover, PopoverArrow, PopoverBackdrop, PopoverClose, PopoverDescription, PopoverParts, PopoverPopup, PopoverPortal, PopoverPositioner, PopoverRoot, PopoverTitle, PopoverTrigger, Prose, ProseSection, QuoteBlock, River, Select, SelectGroup, SelectGroupLabel, SelectOption, SelectPopup, SelectRoot, SelectTrigger, ThemeProvider, Tooltip, TooltipArrow, TooltipParts, TooltipPopup, TooltipPortal, TooltipPositioner, TooltipProvider, TooltipRoot, TooltipTrigger, Tout, TwoColumnSection, USGovBanner, VideoDialog, VideoPlayer, VideoWithBackdrop, VideoWithBackdropBackdrop, VideoWithBackdropContent, VideoWithBackdropParts, VideoWithBackdropRoot, VideoWithBackdropVideo, applyTheme, backgroundGradientVariants, backgroundImageVariants, backgroundOverlayVariants, backgroundStreamVariants, backgroundVariants, backgroundVideoVariants, bannerVariants, blurredVideoBackdropVariants, buttonThemeToStyleVars, buttonVariants, canvasVariants, captionOverlayVariants, cardGridVariants, cardVariants, closeButtonVariants, cn, controlBarVariants, controlButtonVariants, createThemeStyle, dialogBackdropVariants, dialogPopupVariants, filterCSSVars, fontSizeToClass, getToken, gradientOverlayVariants, heroContentVariants, heroHeaderVariants, heroVariants, iconButtonVariants, inputGroupAddonVariants, inputGroupVariants, inputVariants, loadingOverlayVariants, mediaControllerVariants, mergeCSSVars, pagerControlVariants, popoverArrowVariants, popoverPopupVariants, quoteBlockVariants, removeTheme, responsiveTypographyClass, riverVariants, selectOptionVariants, selectPopupVariants, selectTriggerVariants, themeToStyleVars, toCSSVars, tooltipArrowVariants, tooltipPopupVariants, twoColumnSectionVariants, useBreakpoint, useCSSVars, useCanvasBlur, useCaptions, useEventListener, useMaxBreakpoint, useMinBreakpoint, useTheme, useThemeTokens, useVideoKeyboard, videoContainerVariants, videoDialogVariants, videoPlayerVariants, videoWithBackdropVariants };
7290
9274
  //# sourceMappingURL=index.js.map
7291
9275
  //# sourceMappingURL=index.js.map