@brycks/core-front 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/components/data/VirtualList/VirtualList.js +1 -1
  2. package/dist/components/data.cjs +1 -1
  3. package/dist/components/data.d.ts +387 -2
  4. package/dist/components/data.js +26 -26
  5. package/dist/components/feedback/Toast/ToastContext.js +3 -3
  6. package/dist/components/feedback.cjs +1 -1
  7. package/dist/components/feedback.d.ts +317 -2
  8. package/dist/components/feedback.js +21 -21
  9. package/dist/components/form/DropZone/DropZone.cjs.map +1 -1
  10. package/dist/components/form/DropZone/DropZone.js.map +1 -1
  11. package/dist/components/form/FileInput/FileInput.cjs.map +1 -1
  12. package/dist/components/form/FileInput/FileInput.js.map +1 -1
  13. package/dist/components/form/FileUpload/FileUpload.cjs +2 -0
  14. package/dist/components/form/FileUpload/FileUpload.cjs.map +1 -0
  15. package/dist/components/form/FileUpload/FileUpload.js +223 -0
  16. package/dist/components/form/FileUpload/FileUpload.js.map +1 -0
  17. package/dist/components/form/FileUpload/fileUpload.utils.cjs +2 -0
  18. package/dist/components/form/FileUpload/fileUpload.utils.cjs.map +1 -0
  19. package/dist/components/form/FileUpload/fileUpload.utils.js +43 -0
  20. package/dist/components/form/FileUpload/fileUpload.utils.js.map +1 -0
  21. package/dist/components/form/FormGroup/FormGroup.cjs +1 -1
  22. package/dist/components/form/FormGroup/FormGroup.js +1 -1
  23. package/dist/components/form/Slider/Slider.cjs +1 -1
  24. package/dist/components/form/Slider/Slider.js +2 -2
  25. package/dist/components/form/TagInput/TagInput.cjs +1 -1
  26. package/dist/components/form/TagInput/TagInput.js +8 -8
  27. package/dist/components/form.cjs +1 -1
  28. package/dist/components/form.d.ts +889 -2
  29. package/dist/components/form.js +51 -45
  30. package/dist/components/form.js.map +1 -1
  31. package/dist/components/layout.cjs +1 -1
  32. package/dist/components/layout.d.ts +587 -2
  33. package/dist/components/layout.js +30 -30
  34. package/dist/components/media/Video/Video.cjs +1 -1
  35. package/dist/components/media/Video/Video.cjs.map +1 -1
  36. package/dist/components/media/Video/Video.js +54 -54
  37. package/dist/components/media/Video/Video.js.map +1 -1
  38. package/dist/components/navigation/ContextMenu/ContextMenu.cjs +1 -1
  39. package/dist/components/navigation/ContextMenu/ContextMenu.js +5 -5
  40. package/dist/components/navigation/Stepper/Stepper.js +4 -4
  41. package/dist/components/navigation/Tabs/Tabs.js +4 -4
  42. package/dist/components/navigation.cjs +1 -1
  43. package/dist/components/navigation.d.ts +436 -2
  44. package/dist/components/navigation.js +22 -22
  45. package/dist/components/typography/Text/Text.cjs +1 -1
  46. package/dist/components/typography/Text/Text.js +1 -1
  47. package/dist/components/utility.cjs +1 -1
  48. package/dist/components/utility.d.ts +278 -2
  49. package/dist/components/utility.js +28 -28
  50. package/dist/index.cjs +1 -1
  51. package/dist/index.d.ts +87 -0
  52. package/dist/index.js +279 -275
  53. package/dist/index.js.map +1 -1
  54. package/dist/styles.css +1 -1
  55. package/package.json +116 -115
  56. package/dist/data.d.ts +0 -387
  57. package/dist/feedback.d.ts +0 -317
  58. package/dist/form.d.ts +0 -772
  59. package/dist/layout.d.ts +0 -587
  60. package/dist/navigation.d.ts +0 -436
  61. package/dist/utility.d.ts +0 -278
@@ -1 +1 @@
1
- {"version":3,"file":"Video.cjs","sources":["../../../../src/components/media/Video/Video.tsx"],"sourcesContent":["/**\r\n * Video Component\r\n *\r\n * Accessible video player with customizable controls, poster support,\r\n * and respect for user motion preferences.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useRef,\r\n useState,\r\n useCallback,\r\n useEffect,\r\n useImperativeHandle,\r\n type CSSProperties,\r\n type VideoHTMLAttributes,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\r\n\r\nexport type VideoFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type VideoPreload = 'none' | 'metadata' | 'auto'\r\n\r\nexport interface VideoProps\r\n extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'autoPlay'> {\r\n /** Video source URL */\r\n src: string\r\n /** Poster image URL shown before playback */\r\n poster?: string\r\n /** Aspect ratio (width/height) */\r\n aspectRatio?: number | string\r\n /** How the video should fit within its container */\r\n fit?: VideoFit\r\n /** Preload behavior */\r\n preload?: VideoPreload\r\n /**\r\n * Autoplay behavior.\r\n * - true: Autoplay (muted, respects reduced motion)\r\n * - 'muted': Autoplay muted only\r\n * - false: No autoplay\r\n * @default false\r\n */\r\n autoPlay?: boolean | 'muted'\r\n /** Loop video playback */\r\n loop?: boolean\r\n /** Show native controls */\r\n controls?: boolean\r\n /** Start muted */\r\n muted?: boolean\r\n /** Play inline on mobile (vs fullscreen) */\r\n playsInline?: boolean\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Callback when video starts playing */\r\n onPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video pauses */\r\n onPause?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video ends */\r\n onEnded?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video can play */\r\n onCanPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback on error */\r\n onError?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nexport interface VideoRef {\r\n /** Play the video */\r\n play: () => Promise<void>\r\n /** Pause the video */\r\n pause: () => void\r\n /** Toggle play/pause */\r\n toggle: () => void\r\n /** Seek to time in seconds */\r\n seek: (time: number) => void\r\n /** Get current time in seconds */\r\n getCurrentTime: () => number\r\n /** Get duration in seconds */\r\n getDuration: () => number\r\n /** Check if video is playing */\r\n isPlaying: () => boolean\r\n /** Get the underlying video element */\r\n getElement: () => HTMLVideoElement | null\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Video = forwardRef<VideoRef, VideoProps>(function Video(\r\n {\r\n src,\r\n poster,\r\n aspectRatio,\r\n fit = 'cover',\r\n preload = 'metadata',\r\n autoPlay = false,\r\n loop = false,\r\n controls = true,\r\n muted,\r\n playsInline = true,\r\n radius = 'none',\r\n onPlay,\r\n onPause,\r\n onEnded,\r\n onCanPlay,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const videoRef = useRef<HTMLVideoElement>(null)\r\n const [isPlaying, setIsPlaying] = useState(false)\r\n const [hasError, setHasError] = useState(false)\r\n const prefersReducedMotion = usePrefersReducedMotion()\r\n\r\n // Determine if autoplay should be enabled\r\n const shouldAutoPlay = (() => {\r\n // Never autoplay if user prefers reduced motion\r\n if (prefersReducedMotion) return false\r\n if (autoPlay === false) return false\r\n return true\r\n })()\r\n\r\n // Autoplay must be muted to work in most browsers\r\n const shouldMute = muted ?? (shouldAutoPlay || autoPlay === 'muted')\r\n\r\n // Expose imperative handle\r\n useImperativeHandle(\r\n ref,\r\n () => ({\r\n play: async () => {\r\n if (videoRef.current) {\r\n await videoRef.current.play()\r\n }\r\n },\r\n pause: () => {\r\n videoRef.current?.pause()\r\n },\r\n toggle: () => {\r\n if (videoRef.current) {\r\n if (videoRef.current.paused) {\r\n videoRef.current.play()\r\n } else {\r\n videoRef.current.pause()\r\n }\r\n }\r\n },\r\n seek: (time: number) => {\r\n if (videoRef.current) {\r\n videoRef.current.currentTime = time\r\n }\r\n },\r\n getCurrentTime: () => videoRef.current?.currentTime ?? 0,\r\n getDuration: () => videoRef.current?.duration ?? 0,\r\n isPlaying: () => !videoRef.current?.paused,\r\n getElement: () => videoRef.current,\r\n }),\r\n []\r\n )\r\n\r\n // Handle autoplay on mount\r\n useEffect(() => {\r\n if (shouldAutoPlay && videoRef.current) {\r\n // Use a small delay to ensure video is ready\r\n const attemptAutoplay = async () => {\r\n try {\r\n await videoRef.current?.play()\r\n } catch {\r\n // Autoplay was blocked - this is expected in many browsers\r\n // The video will remain paused with poster visible\r\n }\r\n }\r\n attemptAutoplay()\r\n }\r\n }, [shouldAutoPlay])\r\n\r\n const handlePlay = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(true)\r\n onPlay?.(event)\r\n },\r\n [onPlay]\r\n )\r\n\r\n const handlePause = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onPause?.(event)\r\n },\r\n [onPause]\r\n )\r\n\r\n const handleEnded = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onEnded?.(event)\r\n },\r\n [onEnded]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setHasError(true)\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n ...style,\r\n }\r\n\r\n const videoStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: '100%',\r\n height: 'auto',\r\n }),\r\n }\r\n\r\n const errorOverlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n color: 'var(--brycks-foreground-muted)',\r\n fontSize: 'var(--brycks-font-size-sm)',\r\n borderRadius,\r\n }\r\n\r\n if (hasError) {\r\n return (\r\n <div\r\n className={cx('brycks-video', 'brycks-video--error', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label=\"Video failed to load\"\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n <div style={errorOverlayStyle}>\r\n <span>Unable to load video</span>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-video',\r\n isPlaying && 'brycks-video--playing',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n <video\r\n ref={videoRef}\r\n src={src}\r\n poster={poster}\r\n preload={preload}\r\n loop={loop}\r\n controls={controls}\r\n muted={shouldMute}\r\n playsInline={playsInline}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onCanPlay={onCanPlay}\r\n onError={handleError}\r\n style={videoStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nVideo.displayName = 'Video'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Video","forwardRef","src","poster","aspectRatio","fit","preload","autoPlay","loop","controls","muted","playsInline","radius","onPlay","onPause","onEnded","onCanPlay","onError","className","style","testId","props","ref","videoRef","useRef","isPlaying","setIsPlaying","useState","hasError","setHasError","prefersReducedMotion","usePrefersReducedMotion","shouldAutoPlay","shouldMute","useImperativeHandle","time","useEffect","handlePlay","useCallback","event","handlePause","handleEnded","handleError","parsedRatio","borderRadius","containerStyle","videoStyle","errorOverlayStyle","jsxs","cx","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Video.cjs","sources":["../../../../src/components/media/Video/Video.tsx"],"sourcesContent":["/**\r\n * Video Component\r\n *\r\n * Accessible video player with customizable controls, poster support,\r\n * and respect for user motion preferences.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useRef,\r\n useState,\r\n useCallback,\r\n useEffect,\r\n useImperativeHandle,\r\n type CSSProperties,\r\n type VideoHTMLAttributes,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\r\n\r\nexport type VideoFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type VideoPreload = 'none' | 'metadata' | 'auto'\r\n\r\nexport interface VideoProps\r\n extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'autoPlay'> {\r\n /** Video source URL */\r\n src: string\r\n /** Poster image URL shown before playback */\r\n poster?: string\r\n /** Aspect ratio (width/height) */\r\n aspectRatio?: number | string\r\n /** How the video should fit within its container */\r\n fit?: VideoFit\r\n /** Preload behavior */\r\n preload?: VideoPreload\r\n /**\r\n * Autoplay behavior.\r\n * - true: Autoplay (muted, respects reduced motion)\r\n * - 'muted': Autoplay muted only\r\n * - false: No autoplay\r\n * @default false\r\n */\r\n autoPlay?: boolean | 'muted'\r\n /** Loop video playback */\r\n loop?: boolean\r\n /** Show native controls */\r\n controls?: boolean\r\n /** Start muted */\r\n muted?: boolean\r\n /** Play inline on mobile (vs fullscreen) */\r\n playsInline?: boolean\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Callback when video starts playing */\r\n onPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video pauses */\r\n onPause?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video ends */\r\n onEnded?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video can play */\r\n onCanPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback on error */\r\n onError?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nexport interface VideoRef {\r\n /** Play the video */\r\n play: () => Promise<void>\r\n /** Pause the video */\r\n pause: () => void\r\n /** Toggle play/pause */\r\n toggle: () => void\r\n /** Seek to time in seconds */\r\n seek: (time: number) => void\r\n /** Get current time in seconds */\r\n getCurrentTime: () => number\r\n /** Get duration in seconds */\r\n getDuration: () => number\r\n /** Check if video is playing */\r\n isPlaying: () => boolean\r\n /** Get the underlying video element */\r\n getElement: () => HTMLVideoElement | null\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Video = forwardRef<VideoRef, VideoProps>(function Video(\r\n {\r\n src,\r\n poster,\r\n aspectRatio,\r\n fit = 'cover',\r\n preload = 'metadata',\r\n autoPlay = false,\r\n loop = false,\r\n controls = true,\r\n muted,\r\n playsInline = true,\r\n radius = 'none',\r\n onPlay,\r\n onPause,\r\n onEnded,\r\n onCanPlay,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const videoRef = useRef<HTMLVideoElement>(null)\r\n const [isPlaying, setIsPlaying] = useState(false)\r\n const [hasError, setHasError] = useState(false)\r\n const prefersReducedMotion = usePrefersReducedMotion()\r\n\r\n // Determine if autoplay should be enabled\r\n const shouldAutoPlay = (() => {\r\n // Never autoplay if user prefers reduced motion\r\n if (prefersReducedMotion) return false\r\n if (autoPlay === false) return false\r\n return true\r\n })()\r\n\r\n // Autoplay must be muted to work in most browsers\r\n const shouldMute = muted ?? (shouldAutoPlay || autoPlay === 'muted')\r\n\r\n // Expose imperative handle\r\n useImperativeHandle(\r\n ref,\r\n () => ({\r\n play: async () => {\r\n if (videoRef.current) {\r\n await videoRef.current.play()\r\n }\r\n },\r\n pause: () => {\r\n videoRef.current?.pause()\r\n },\r\n toggle: () => {\r\n if (videoRef.current) {\r\n if (videoRef.current.paused) {\r\n videoRef.current.play()\r\n } else {\r\n videoRef.current.pause()\r\n }\r\n }\r\n },\r\n seek: (time: number) => {\r\n if (videoRef.current) {\r\n videoRef.current.currentTime = time\r\n }\r\n },\r\n getCurrentTime: () => videoRef.current?.currentTime ?? 0,\r\n getDuration: () => videoRef.current?.duration ?? 0,\r\n isPlaying: () => !videoRef.current?.paused,\r\n getElement: () => videoRef.current,\r\n }),\r\n []\r\n )\r\n\r\n // Handle autoplay on mount\r\n useEffect(() => {\r\n if (shouldAutoPlay && videoRef.current) {\r\n // Use a small delay to ensure video is ready\r\n const attemptAutoplay = async () => {\r\n try {\r\n await videoRef.current?.play()\r\n } catch {\r\n // Autoplay was blocked - this is expected in many browsers\r\n // The video will remain paused with poster visible\r\n }\r\n }\r\n attemptAutoplay()\r\n }\r\n }, [shouldAutoPlay])\r\n\r\n const handlePlay = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(true)\r\n onPlay?.(event)\r\n },\r\n [onPlay]\r\n )\r\n\r\n const handlePause = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onPause?.(event)\r\n },\r\n [onPause]\r\n )\r\n\r\n const handleEnded = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onEnded?.(event)\r\n },\r\n [onEnded]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setHasError(true)\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n ...style,\r\n }\r\n\r\n const videoStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: '100%',\r\n height: 'auto',\r\n }),\r\n }\r\n\r\n const errorOverlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n color: 'var(--brycks-foreground-muted)',\r\n fontSize: 'var(--brycks-font-size-sm)',\r\n borderRadius,\r\n }\r\n\r\n if (hasError) {\r\n return (\r\n <div\r\n className={cx('brycks-video', 'brycks-video--error', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label=\"Video failed to load\"\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n <div style={errorOverlayStyle}>\r\n <span>Unable to load video</span>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-video',\r\n isPlaying && 'brycks-video--playing',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n <video\r\n ref={videoRef}\r\n src={src}\r\n poster={poster}\r\n preload={preload}\r\n loop={loop}\r\n controls={controls}\r\n muted={shouldMute}\r\n playsInline={playsInline}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onCanPlay={onCanPlay}\r\n onError={handleError}\r\n style={videoStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nVideo.displayName = 'Video'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Video","forwardRef","src","poster","aspectRatio","fit","preload","autoPlay","loop","controls","muted","playsInline","radius","onPlay","onPause","onEnded","onCanPlay","onError","className","style","testId","props","ref","videoRef","useRef","isPlaying","setIsPlaying","useState","hasError","setHasError","shouldAutoPlay","usePrefersReducedMotion","shouldMute","useImperativeHandle","time","useEffect","handlePlay","useCallback","event","handlePause","handleEnded","handleError","parsedRatio","borderRadius","containerStyle","videoStyle","errorOverlayStyle","jsxs","cx","jsx"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { jsxs as J, jsx as n } from "react/jsx-runtime";
2
- import { forwardRef as K, useRef as L, useState as w, useImperativeHandle as Q, useEffect as W, useCallback as c } from "react";
3
- import { cx as N } from "../../../utils/styles.js";
4
- import { usePrefersReducedMotion as X } from "../../../hooks/useMediaQuery.js";
5
- const R = {
1
+ import { jsxs as G, jsx as n } from "react/jsx-runtime";
2
+ import { forwardRef as J, useRef as K, useState as R, useImperativeHandle as L, useEffect as Q, useCallback as c } from "react";
3
+ import { cx as w } from "../../../utils/styles.js";
4
+ import { usePrefersReducedMotion as W } from "../../../hooks/useMediaQuery.js";
5
+ const N = {
6
6
  none: "0",
7
7
  sm: "var(--brycks-radius-sm)",
8
8
  md: "var(--brycks-radius-md)",
@@ -10,42 +10,42 @@ const R = {
10
10
  xl: "var(--brycks-radius-xl)",
11
11
  full: "var(--brycks-radius-full)"
12
12
  };
13
- function Y(r) {
13
+ function X(r) {
14
14
  if (r === void 0) return;
15
15
  if (typeof r == "number") return r;
16
- const o = r.split(/[:/]/);
17
- if (o.length === 2) {
18
- const l = parseFloat(o[0]), a = parseFloat(o[1]);
19
- if (!isNaN(l) && !isNaN(a) && a !== 0)
20
- return l / a;
16
+ const s = r.split(/[:/]/);
17
+ if (s.length === 2) {
18
+ const d = parseFloat(s[0]), a = parseFloat(s[1]);
19
+ if (!isNaN(d) && !isNaN(a) && a !== 0)
20
+ return d / a;
21
21
  }
22
22
  const i = parseFloat(r);
23
23
  return isNaN(i) ? void 0 : i;
24
24
  }
25
- const Z = K(function({
26
- src: o,
25
+ const Y = J(function({
26
+ src: s,
27
27
  poster: i,
28
- aspectRatio: l,
28
+ aspectRatio: d,
29
29
  fit: a = "cover",
30
30
  preload: x = "metadata",
31
31
  autoPlay: p = !1,
32
32
  loop: E = !1,
33
33
  controls: P = !0,
34
34
  muted: C,
35
- playsInline: S = !0,
36
- radius: j = "none",
35
+ playsInline: M = !0,
36
+ radius: S = "none",
37
37
  onPlay: y,
38
38
  onPause: m,
39
39
  onEnded: v,
40
- onCanPlay: A,
40
+ onCanPlay: j,
41
41
  onError: b,
42
42
  className: g,
43
- style: F,
43
+ style: A,
44
44
  testId: h,
45
- ...M
45
+ ...F
46
46
  }, V) {
47
- const e = L(null), [T, u] = w(!1), [z, B] = w(!1), H = X(), f = !(H || p === !1), I = C ?? (f || p === "muted");
48
- Q(
47
+ const e = K(null), [T, u] = R(!1), [z, B] = R(!1), f = !(W() || p === !1), H = C ?? (f || p === "muted");
48
+ L(
49
49
  V,
50
50
  () => ({
51
51
  play: async () => {
@@ -66,7 +66,7 @@ const Z = K(function({
66
66
  getElement: () => e.current
67
67
  }),
68
68
  []
69
- ), W(() => {
69
+ ), Q(() => {
70
70
  f && e.current && (async () => {
71
71
  try {
72
72
  await e.current?.play();
@@ -74,41 +74,41 @@ const Z = K(function({
74
74
  }
75
75
  })();
76
76
  }, [f]);
77
- const $ = c(
77
+ const I = c(
78
78
  (t) => {
79
79
  u(!0), y?.(t);
80
80
  },
81
81
  [y]
82
- ), D = c(
82
+ ), $ = c(
83
83
  (t) => {
84
84
  u(!1), m?.(t);
85
85
  },
86
86
  [m]
87
- ), O = c(
87
+ ), D = c(
88
88
  (t) => {
89
89
  u(!1), v?.(t);
90
90
  },
91
91
  [v]
92
- ), U = c(
92
+ ), O = c(
93
93
  (t) => {
94
94
  B(!0), b?.(t);
95
95
  },
96
96
  [b]
97
- ), s = Y(l), d = R[j] ?? R.none, k = {
97
+ ), o = X(d), l = N[S] ?? N.none, k = {
98
98
  position: "relative",
99
99
  overflow: "hidden",
100
- borderRadius: d,
100
+ borderRadius: l,
101
101
  backgroundColor: "var(--brycks-background-muted)",
102
- ...s ? {
102
+ ...o ? {
103
103
  width: "100%",
104
- paddingBottom: `${1 / s * 100}%`
104
+ paddingBottom: `${1 / o * 100}%`
105
105
  } : {},
106
- ...F
107
- }, q = {
106
+ ...A
107
+ }, U = {
108
108
  display: "block",
109
109
  objectFit: a,
110
- borderRadius: d,
111
- ...s ? {
110
+ borderRadius: l,
111
+ ...o ? {
112
112
  position: "absolute",
113
113
  top: 0,
114
114
  left: 0,
@@ -118,7 +118,7 @@ const Z = K(function({
118
118
  width: "100%",
119
119
  height: "auto"
120
120
  }
121
- }, G = {
121
+ }, q = {
122
122
  position: "absolute",
123
123
  top: 0,
124
124
  left: 0,
@@ -130,56 +130,56 @@ const Z = K(function({
130
130
  backgroundColor: "var(--brycks-background-muted)",
131
131
  color: "var(--brycks-foreground-muted)",
132
132
  fontSize: "var(--brycks-font-size-sm)",
133
- borderRadius: d
133
+ borderRadius: l
134
134
  };
135
- return z ? /* @__PURE__ */ J(
135
+ return z ? /* @__PURE__ */ G(
136
136
  "div",
137
137
  {
138
- className: N("brycks-video", "brycks-video--error", g),
138
+ className: w("brycks-video", "brycks-video--error", g),
139
139
  style: k,
140
140
  "data-testid": h,
141
141
  role: "img",
142
142
  "aria-label": "Video failed to load",
143
143
  children: [
144
- s && /* @__PURE__ */ n("div", { style: { paddingBottom: `${1 / s * 100}%` } }),
145
- /* @__PURE__ */ n("div", { style: G, children: /* @__PURE__ */ n("span", { children: "Unable to load video" }) })
144
+ o && /* @__PURE__ */ n("div", { style: { paddingBottom: `${1 / o * 100}%` } }),
145
+ /* @__PURE__ */ n("div", { style: q, children: /* @__PURE__ */ n("span", { children: "Unable to load video" }) })
146
146
  ]
147
147
  }
148
148
  ) : /* @__PURE__ */ n(
149
149
  "div",
150
150
  {
151
- className: N(
151
+ className: w(
152
152
  "brycks-video",
153
153
  T && "brycks-video--playing",
154
154
  g
155
155
  ),
156
- style: s ? k : { position: "relative", borderRadius: d },
156
+ style: o ? k : { position: "relative", borderRadius: l },
157
157
  "data-testid": h,
158
158
  children: /* @__PURE__ */ n(
159
159
  "video",
160
160
  {
161
161
  ref: e,
162
- src: o,
162
+ src: s,
163
163
  poster: i,
164
164
  preload: x,
165
165
  loop: E,
166
166
  controls: P,
167
- muted: I,
168
- playsInline: S,
169
- onPlay: $,
170
- onPause: D,
171
- onEnded: O,
172
- onCanPlay: A,
173
- onError: U,
174
- style: q,
175
- ...M
167
+ muted: H,
168
+ playsInline: M,
169
+ onPlay: I,
170
+ onPause: $,
171
+ onEnded: D,
172
+ onCanPlay: j,
173
+ onError: O,
174
+ style: U,
175
+ ...F
176
176
  }
177
177
  )
178
178
  }
179
179
  );
180
180
  });
181
- Z.displayName = "Video";
181
+ Y.displayName = "Video";
182
182
  export {
183
- Z as Video
183
+ Y as Video
184
184
  };
185
185
  //# sourceMappingURL=Video.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Video.js","sources":["../../../../src/components/media/Video/Video.tsx"],"sourcesContent":["/**\r\n * Video Component\r\n *\r\n * Accessible video player with customizable controls, poster support,\r\n * and respect for user motion preferences.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useRef,\r\n useState,\r\n useCallback,\r\n useEffect,\r\n useImperativeHandle,\r\n type CSSProperties,\r\n type VideoHTMLAttributes,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\r\n\r\nexport type VideoFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type VideoPreload = 'none' | 'metadata' | 'auto'\r\n\r\nexport interface VideoProps\r\n extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'autoPlay'> {\r\n /** Video source URL */\r\n src: string\r\n /** Poster image URL shown before playback */\r\n poster?: string\r\n /** Aspect ratio (width/height) */\r\n aspectRatio?: number | string\r\n /** How the video should fit within its container */\r\n fit?: VideoFit\r\n /** Preload behavior */\r\n preload?: VideoPreload\r\n /**\r\n * Autoplay behavior.\r\n * - true: Autoplay (muted, respects reduced motion)\r\n * - 'muted': Autoplay muted only\r\n * - false: No autoplay\r\n * @default false\r\n */\r\n autoPlay?: boolean | 'muted'\r\n /** Loop video playback */\r\n loop?: boolean\r\n /** Show native controls */\r\n controls?: boolean\r\n /** Start muted */\r\n muted?: boolean\r\n /** Play inline on mobile (vs fullscreen) */\r\n playsInline?: boolean\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Callback when video starts playing */\r\n onPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video pauses */\r\n onPause?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video ends */\r\n onEnded?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video can play */\r\n onCanPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback on error */\r\n onError?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nexport interface VideoRef {\r\n /** Play the video */\r\n play: () => Promise<void>\r\n /** Pause the video */\r\n pause: () => void\r\n /** Toggle play/pause */\r\n toggle: () => void\r\n /** Seek to time in seconds */\r\n seek: (time: number) => void\r\n /** Get current time in seconds */\r\n getCurrentTime: () => number\r\n /** Get duration in seconds */\r\n getDuration: () => number\r\n /** Check if video is playing */\r\n isPlaying: () => boolean\r\n /** Get the underlying video element */\r\n getElement: () => HTMLVideoElement | null\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Video = forwardRef<VideoRef, VideoProps>(function Video(\r\n {\r\n src,\r\n poster,\r\n aspectRatio,\r\n fit = 'cover',\r\n preload = 'metadata',\r\n autoPlay = false,\r\n loop = false,\r\n controls = true,\r\n muted,\r\n playsInline = true,\r\n radius = 'none',\r\n onPlay,\r\n onPause,\r\n onEnded,\r\n onCanPlay,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const videoRef = useRef<HTMLVideoElement>(null)\r\n const [isPlaying, setIsPlaying] = useState(false)\r\n const [hasError, setHasError] = useState(false)\r\n const prefersReducedMotion = usePrefersReducedMotion()\r\n\r\n // Determine if autoplay should be enabled\r\n const shouldAutoPlay = (() => {\r\n // Never autoplay if user prefers reduced motion\r\n if (prefersReducedMotion) return false\r\n if (autoPlay === false) return false\r\n return true\r\n })()\r\n\r\n // Autoplay must be muted to work in most browsers\r\n const shouldMute = muted ?? (shouldAutoPlay || autoPlay === 'muted')\r\n\r\n // Expose imperative handle\r\n useImperativeHandle(\r\n ref,\r\n () => ({\r\n play: async () => {\r\n if (videoRef.current) {\r\n await videoRef.current.play()\r\n }\r\n },\r\n pause: () => {\r\n videoRef.current?.pause()\r\n },\r\n toggle: () => {\r\n if (videoRef.current) {\r\n if (videoRef.current.paused) {\r\n videoRef.current.play()\r\n } else {\r\n videoRef.current.pause()\r\n }\r\n }\r\n },\r\n seek: (time: number) => {\r\n if (videoRef.current) {\r\n videoRef.current.currentTime = time\r\n }\r\n },\r\n getCurrentTime: () => videoRef.current?.currentTime ?? 0,\r\n getDuration: () => videoRef.current?.duration ?? 0,\r\n isPlaying: () => !videoRef.current?.paused,\r\n getElement: () => videoRef.current,\r\n }),\r\n []\r\n )\r\n\r\n // Handle autoplay on mount\r\n useEffect(() => {\r\n if (shouldAutoPlay && videoRef.current) {\r\n // Use a small delay to ensure video is ready\r\n const attemptAutoplay = async () => {\r\n try {\r\n await videoRef.current?.play()\r\n } catch {\r\n // Autoplay was blocked - this is expected in many browsers\r\n // The video will remain paused with poster visible\r\n }\r\n }\r\n attemptAutoplay()\r\n }\r\n }, [shouldAutoPlay])\r\n\r\n const handlePlay = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(true)\r\n onPlay?.(event)\r\n },\r\n [onPlay]\r\n )\r\n\r\n const handlePause = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onPause?.(event)\r\n },\r\n [onPause]\r\n )\r\n\r\n const handleEnded = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onEnded?.(event)\r\n },\r\n [onEnded]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setHasError(true)\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n ...style,\r\n }\r\n\r\n const videoStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: '100%',\r\n height: 'auto',\r\n }),\r\n }\r\n\r\n const errorOverlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n color: 'var(--brycks-foreground-muted)',\r\n fontSize: 'var(--brycks-font-size-sm)',\r\n borderRadius,\r\n }\r\n\r\n if (hasError) {\r\n return (\r\n <div\r\n className={cx('brycks-video', 'brycks-video--error', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label=\"Video failed to load\"\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n <div style={errorOverlayStyle}>\r\n <span>Unable to load video</span>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-video',\r\n isPlaying && 'brycks-video--playing',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n <video\r\n ref={videoRef}\r\n src={src}\r\n poster={poster}\r\n preload={preload}\r\n loop={loop}\r\n controls={controls}\r\n muted={shouldMute}\r\n playsInline={playsInline}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onCanPlay={onCanPlay}\r\n onError={handleError}\r\n style={videoStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nVideo.displayName = 'Video'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Video","forwardRef","src","poster","aspectRatio","fit","preload","autoPlay","loop","controls","muted","playsInline","radius","onPlay","onPause","onEnded","onCanPlay","onError","className","style","testId","props","ref","videoRef","useRef","isPlaying","setIsPlaying","useState","hasError","setHasError","prefersReducedMotion","usePrefersReducedMotion","shouldAutoPlay","shouldMute","useImperativeHandle","time","useEffect","handlePlay","useCallback","event","handlePause","handleEnded","handleError","parsedRatio","borderRadius","containerStyle","videoStyle","errorOverlayStyle","jsxs","cx","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Video.js","sources":["../../../../src/components/media/Video/Video.tsx"],"sourcesContent":["/**\r\n * Video Component\r\n *\r\n * Accessible video player with customizable controls, poster support,\r\n * and respect for user motion preferences.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useRef,\r\n useState,\r\n useCallback,\r\n useEffect,\r\n useImperativeHandle,\r\n type CSSProperties,\r\n type VideoHTMLAttributes,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\nimport { usePrefersReducedMotion } from '../../../hooks/useMediaQuery'\r\n\r\nexport type VideoFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type VideoPreload = 'none' | 'metadata' | 'auto'\r\n\r\nexport interface VideoProps\r\n extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'autoPlay'> {\r\n /** Video source URL */\r\n src: string\r\n /** Poster image URL shown before playback */\r\n poster?: string\r\n /** Aspect ratio (width/height) */\r\n aspectRatio?: number | string\r\n /** How the video should fit within its container */\r\n fit?: VideoFit\r\n /** Preload behavior */\r\n preload?: VideoPreload\r\n /**\r\n * Autoplay behavior.\r\n * - true: Autoplay (muted, respects reduced motion)\r\n * - 'muted': Autoplay muted only\r\n * - false: No autoplay\r\n * @default false\r\n */\r\n autoPlay?: boolean | 'muted'\r\n /** Loop video playback */\r\n loop?: boolean\r\n /** Show native controls */\r\n controls?: boolean\r\n /** Start muted */\r\n muted?: boolean\r\n /** Play inline on mobile (vs fullscreen) */\r\n playsInline?: boolean\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Callback when video starts playing */\r\n onPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video pauses */\r\n onPause?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video ends */\r\n onEnded?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback when video can play */\r\n onCanPlay?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Callback on error */\r\n onError?: (event: SyntheticEvent<HTMLVideoElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nexport interface VideoRef {\r\n /** Play the video */\r\n play: () => Promise<void>\r\n /** Pause the video */\r\n pause: () => void\r\n /** Toggle play/pause */\r\n toggle: () => void\r\n /** Seek to time in seconds */\r\n seek: (time: number) => void\r\n /** Get current time in seconds */\r\n getCurrentTime: () => number\r\n /** Get duration in seconds */\r\n getDuration: () => number\r\n /** Check if video is playing */\r\n isPlaying: () => boolean\r\n /** Get the underlying video element */\r\n getElement: () => HTMLVideoElement | null\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Video = forwardRef<VideoRef, VideoProps>(function Video(\r\n {\r\n src,\r\n poster,\r\n aspectRatio,\r\n fit = 'cover',\r\n preload = 'metadata',\r\n autoPlay = false,\r\n loop = false,\r\n controls = true,\r\n muted,\r\n playsInline = true,\r\n radius = 'none',\r\n onPlay,\r\n onPause,\r\n onEnded,\r\n onCanPlay,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const videoRef = useRef<HTMLVideoElement>(null)\r\n const [isPlaying, setIsPlaying] = useState(false)\r\n const [hasError, setHasError] = useState(false)\r\n const prefersReducedMotion = usePrefersReducedMotion()\r\n\r\n // Determine if autoplay should be enabled\r\n const shouldAutoPlay = (() => {\r\n // Never autoplay if user prefers reduced motion\r\n if (prefersReducedMotion) return false\r\n if (autoPlay === false) return false\r\n return true\r\n })()\r\n\r\n // Autoplay must be muted to work in most browsers\r\n const shouldMute = muted ?? (shouldAutoPlay || autoPlay === 'muted')\r\n\r\n // Expose imperative handle\r\n useImperativeHandle(\r\n ref,\r\n () => ({\r\n play: async () => {\r\n if (videoRef.current) {\r\n await videoRef.current.play()\r\n }\r\n },\r\n pause: () => {\r\n videoRef.current?.pause()\r\n },\r\n toggle: () => {\r\n if (videoRef.current) {\r\n if (videoRef.current.paused) {\r\n videoRef.current.play()\r\n } else {\r\n videoRef.current.pause()\r\n }\r\n }\r\n },\r\n seek: (time: number) => {\r\n if (videoRef.current) {\r\n videoRef.current.currentTime = time\r\n }\r\n },\r\n getCurrentTime: () => videoRef.current?.currentTime ?? 0,\r\n getDuration: () => videoRef.current?.duration ?? 0,\r\n isPlaying: () => !videoRef.current?.paused,\r\n getElement: () => videoRef.current,\r\n }),\r\n []\r\n )\r\n\r\n // Handle autoplay on mount\r\n useEffect(() => {\r\n if (shouldAutoPlay && videoRef.current) {\r\n // Use a small delay to ensure video is ready\r\n const attemptAutoplay = async () => {\r\n try {\r\n await videoRef.current?.play()\r\n } catch {\r\n // Autoplay was blocked - this is expected in many browsers\r\n // The video will remain paused with poster visible\r\n }\r\n }\r\n attemptAutoplay()\r\n }\r\n }, [shouldAutoPlay])\r\n\r\n const handlePlay = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(true)\r\n onPlay?.(event)\r\n },\r\n [onPlay]\r\n )\r\n\r\n const handlePause = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onPause?.(event)\r\n },\r\n [onPause]\r\n )\r\n\r\n const handleEnded = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setIsPlaying(false)\r\n onEnded?.(event)\r\n },\r\n [onEnded]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLVideoElement>) => {\r\n setHasError(true)\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n ...style,\r\n }\r\n\r\n const videoStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: '100%',\r\n height: 'auto',\r\n }),\r\n }\r\n\r\n const errorOverlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n color: 'var(--brycks-foreground-muted)',\r\n fontSize: 'var(--brycks-font-size-sm)',\r\n borderRadius,\r\n }\r\n\r\n if (hasError) {\r\n return (\r\n <div\r\n className={cx('brycks-video', 'brycks-video--error', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label=\"Video failed to load\"\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n <div style={errorOverlayStyle}>\r\n <span>Unable to load video</span>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-video',\r\n isPlaying && 'brycks-video--playing',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n <video\r\n ref={videoRef}\r\n src={src}\r\n poster={poster}\r\n preload={preload}\r\n loop={loop}\r\n controls={controls}\r\n muted={shouldMute}\r\n playsInline={playsInline}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onCanPlay={onCanPlay}\r\n onError={handleError}\r\n style={videoStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nVideo.displayName = 'Video'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Video","forwardRef","src","poster","aspectRatio","fit","preload","autoPlay","loop","controls","muted","playsInline","radius","onPlay","onPause","onEnded","onCanPlay","onError","className","style","testId","props","ref","videoRef","useRef","isPlaying","setIsPlaying","useState","hasError","setHasError","shouldAutoPlay","usePrefersReducedMotion","shouldMute","useImperativeHandle","time","useEffect","handlePlay","useCallback","event","handlePause","handleEnded","handleError","parsedRatio","borderRadius","containerStyle","videoStyle","errorOverlayStyle","jsxs","cx","jsx"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),r=require("react"),z=require("react-dom"),L=require("../../../utils/styles.cjs"),v=require("../../../design-system/primitives/sizing.cjs"),M=require("../../../design-system/tokens/spacing.cjs"),S=require("../../../design-system/tokens/motion.cjs"),j=require("../../../design-system/tokens/typography.cjs"),I=r.createContext(null);function R(){return o.jsx("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",children:o.jsx("path",{d:"M4.5 3l3 3-3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function P({items:i,position:h,onClose:u,level:p=0}){const[l,x]=r.useState(-1),[b,c]=r.useState(null),y=r.useRef(null),a=i.filter(e=>!e.separator&&!e.disabled),g=r.useCallback(e=>{switch(e.key){case"ArrowDown":e.preventDefault(),e.stopPropagation(),x(n=>{const s=n+1;return s>=a.length?0:s});break;case"ArrowUp":e.preventDefault(),e.stopPropagation(),x(n=>{const s=n-1;return s<0?a.length-1:s});break;case"ArrowRight":{e.preventDefault(),e.stopPropagation();const n=a[l];if(n?.children){const s=i.indexOf(n);c(s)}break}case"ArrowLeft":p>0&&(e.preventDefault(),e.stopPropagation(),u());break;case"Enter":case" ":if(e.preventDefault(),e.stopPropagation(),l>=0){const n=a[l];if(n?.children){const s=i.indexOf(n);c(s)}else n?.onClick&&(n.onClick(),u())}break;case"Escape":e.preventDefault(),e.stopPropagation(),u();break}},[l,a,i,p,u]);r.useEffect(()=>{y.current?.focus()},[]);const w={position:"fixed",top:h.y,left:h.x,minWidth:180,maxWidth:280,backgroundColor:"var(--brycks-background-elevated)",border:"1px solid var(--brycks-border-default)",borderRadius:"var(--brycks-radius-lg)",boxShadow:"var(--brycks-shadow-lg)",padding:M.spacing[1],zIndex:"var(--brycks-z-dropdown)",outline:"none"},C=(e,n)=>({display:"flex",alignItems:"center",gap:M.spacing[2],padding:`${v.componentPaddingY.sm}px ${v.componentPaddingX.sm}px`,fontSize:j.fontSizes.sm,fontWeight:400,color:n?"var(--brycks-foreground-disabled)":"var(--brycks-foreground-default)",backgroundColor:e?"var(--brycks-background-muted)":"transparent",borderRadius:"var(--brycks-radius-md)",cursor:n?"not-allowed":"pointer",transition:`background-color ${S.durations.fast}ms ${S.easings.easeOut}`}),k={display:"flex",alignItems:"center",justifyContent:"center",width:v.iconSizes.sm,height:v.iconSizes.sm,color:"inherit"},d={marginLeft:"auto",fontSize:j.fontSizes.xs,color:"var(--brycks-foreground-muted)"},m={height:1,margin:`${M.spacing[1]}px 0`,backgroundColor:"var(--brycks-border-default)"};let t=-1;return o.jsx("ul",{ref:y,role:"menu",tabIndex:0,style:w,onKeyDown:g,children:i.map((e,n)=>{if(e.separator)return o.jsx("li",{role:"separator",style:m},e.id);e.disabled||t++;const s=t,E=!e.disabled&&s===l,f=e.children&&e.children.length>0;return o.jsxs("li",{role:"menuitem","aria-disabled":e.disabled,"aria-haspopup":f?"menu":void 0,"aria-expanded":f&&b===n?"true":void 0,style:C(E,!!e.disabled),onMouseEnter:()=>{e.disabled||(x(s),c(f?n:null))},onMouseLeave:()=>{f||c(null)},onClick:()=>{e.disabled||(f?c(n):e.onClick&&(e.onClick(),u()))},children:[e.icon&&o.jsx("span",{style:k,children:e.icon}),o.jsx("span",{style:{flex:1},children:e.label}),e.shortcut&&o.jsx("span",{style:d,children:e.shortcut}),f&&o.jsx("span",{style:k,children:o.jsx(R,{})}),f&&b===n&&e.children&&o.jsx(P,{items:e.children,position:{x:176,y:0},onClose:()=>c(null),level:p+1})]},e.id)})})}const D=r.forwardRef(function({items:h,children:u,onOpen:p,onClose:l,disabled:x=!1,className:b,testId:c},y){const[a,g]=r.useState(!1),[w,C]=r.useState({x:0,y:0}),k=r.useCallback(t=>{if(x)return;t.preventDefault(),t.stopPropagation();const e=Math.min(t.clientX,window.innerWidth-200),n=Math.min(t.clientY,window.innerHeight-300);C({x:e,y:n}),g(!0),p?.()},[x,p]),d=r.useCallback(()=>{g(!1),l?.()},[l]);r.useEffect(()=>{if(!a)return;const t=()=>{d()};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[a,d]),r.useEffect(()=>{if(!a)return;const t=e=>{e.key==="Escape"&&d()};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[a,d]);const m={display:"contents"};return o.jsx(I.Provider,{value:{closeMenu:d},children:o.jsxs("div",{ref:y,className:L.cx("brycks-contextmenu",b),style:m,"data-testid":c,onContextMenu:k,children:[u,a&&z.createPortal(o.jsx("div",{style:{position:"fixed",inset:0,zIndex:"var(--brycks-z-dropdown)"},onMouseDown:t=>t.stopPropagation(),children:o.jsx(P,{items:h,position:w,onClose:d})}),document.body)]})})});D.displayName="ContextMenu";function q(){const i=r.useContext(I);if(!i)throw new Error("useContextMenu must be used within a ContextMenu");return i}exports.ContextMenu=D;exports.useContextMenu=q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),r=require("react"),z=require("react-dom"),L=require("../../../utils/styles.cjs"),M=require("../../../design-system/tokens/spacing.cjs"),v=require("../../../design-system/primitives/sizing.cjs"),S=require("../../../design-system/tokens/typography.cjs"),j=require("../../../design-system/tokens/motion.cjs"),I=r.createContext(null);function R(){return o.jsx("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",children:o.jsx("path",{d:"M4.5 3l3 3-3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function P({items:i,position:h,onClose:u,level:p=0}){const[l,x]=r.useState(-1),[b,c]=r.useState(null),y=r.useRef(null),a=i.filter(e=>!e.separator&&!e.disabled),g=r.useCallback(e=>{switch(e.key){case"ArrowDown":e.preventDefault(),e.stopPropagation(),x(n=>{const s=n+1;return s>=a.length?0:s});break;case"ArrowUp":e.preventDefault(),e.stopPropagation(),x(n=>{const s=n-1;return s<0?a.length-1:s});break;case"ArrowRight":{e.preventDefault(),e.stopPropagation();const n=a[l];if(n?.children){const s=i.indexOf(n);c(s)}break}case"ArrowLeft":p>0&&(e.preventDefault(),e.stopPropagation(),u());break;case"Enter":case" ":if(e.preventDefault(),e.stopPropagation(),l>=0){const n=a[l];if(n?.children){const s=i.indexOf(n);c(s)}else n?.onClick&&(n.onClick(),u())}break;case"Escape":e.preventDefault(),e.stopPropagation(),u();break}},[l,a,i,p,u]);r.useEffect(()=>{y.current?.focus()},[]);const w={position:"fixed",top:h.y,left:h.x,minWidth:180,maxWidth:280,backgroundColor:"var(--brycks-background-elevated)",border:"1px solid var(--brycks-border-default)",borderRadius:"var(--brycks-radius-lg)",boxShadow:"var(--brycks-shadow-lg)",padding:M.spacing[1],zIndex:"var(--brycks-z-dropdown)",outline:"none"},C=(e,n)=>({display:"flex",alignItems:"center",gap:M.spacing[2],padding:`${v.componentPaddingY.sm}px ${v.componentPaddingX.sm}px`,fontSize:S.fontSizes.sm,fontWeight:400,color:n?"var(--brycks-foreground-disabled)":"var(--brycks-foreground-default)",backgroundColor:e?"var(--brycks-background-muted)":"transparent",borderRadius:"var(--brycks-radius-md)",cursor:n?"not-allowed":"pointer",transition:`background-color ${j.durations.fast}ms ${j.easings.easeOut}`}),k={display:"flex",alignItems:"center",justifyContent:"center",width:v.iconSizes.sm,height:v.iconSizes.sm,color:"inherit"},d={marginLeft:"auto",fontSize:S.fontSizes.xs,color:"var(--brycks-foreground-muted)"},m={height:1,margin:`${M.spacing[1]}px 0`,backgroundColor:"var(--brycks-border-default)"};let t=-1;return o.jsx("ul",{ref:y,role:"menu",tabIndex:0,style:w,onKeyDown:g,children:i.map((e,n)=>{if(e.separator)return o.jsx("li",{role:"separator",style:m},e.id);e.disabled||t++;const s=t,E=!e.disabled&&s===l,f=e.children&&e.children.length>0;return o.jsxs("li",{role:"menuitem","aria-disabled":e.disabled,"aria-haspopup":f?"menu":void 0,"aria-expanded":f&&b===n?"true":void 0,style:C(E,!!e.disabled),onMouseEnter:()=>{e.disabled||(x(s),c(f?n:null))},onMouseLeave:()=>{f||c(null)},onClick:()=>{e.disabled||(f?c(n):e.onClick&&(e.onClick(),u()))},children:[e.icon&&o.jsx("span",{style:k,children:e.icon}),o.jsx("span",{style:{flex:1},children:e.label}),e.shortcut&&o.jsx("span",{style:d,children:e.shortcut}),f&&o.jsx("span",{style:k,children:o.jsx(R,{})}),f&&b===n&&e.children&&o.jsx(P,{items:e.children,position:{x:176,y:0},onClose:()=>c(null),level:p+1})]},e.id)})})}const D=r.forwardRef(function({items:h,children:u,onOpen:p,onClose:l,disabled:x=!1,className:b,testId:c},y){const[a,g]=r.useState(!1),[w,C]=r.useState({x:0,y:0}),k=r.useCallback(t=>{if(x)return;t.preventDefault(),t.stopPropagation();const e=Math.min(t.clientX,window.innerWidth-200),n=Math.min(t.clientY,window.innerHeight-300);C({x:e,y:n}),g(!0),p?.()},[x,p]),d=r.useCallback(()=>{g(!1),l?.()},[l]);r.useEffect(()=>{if(!a)return;const t=()=>{d()};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[a,d]),r.useEffect(()=>{if(!a)return;const t=e=>{e.key==="Escape"&&d()};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[a,d]);const m={display:"contents"};return o.jsx(I.Provider,{value:{closeMenu:d},children:o.jsxs("div",{ref:y,className:L.cx("brycks-contextmenu",b),style:m,"data-testid":c,onContextMenu:k,children:[u,a&&z.createPortal(o.jsx("div",{style:{position:"fixed",inset:0,zIndex:"var(--brycks-z-dropdown)"},onMouseDown:t=>t.stopPropagation(),children:o.jsx(P,{items:h,position:w,onClose:d})}),document.body)]})})});D.displayName="ContextMenu";function q(){const i=r.useContext(I);if(!i)throw new Error("useContextMenu must be used within a ContextMenu");return i}exports.ContextMenu=D;exports.useContextMenu=q;
2
2
  //# sourceMappingURL=ContextMenu.cjs.map
@@ -1,12 +1,12 @@
1
1
  import { jsx as o, jsxs as D } from "react/jsx-runtime";
2
- import { forwardRef as R, useState as k, useCallback as M, useEffect as I, createContext as A, useContext as W, useRef as $ } from "react";
2
+ import { forwardRef as R, useState as k, useCallback as M, useEffect as I, useContext as A, createContext as W, useRef as $ } from "react";
3
3
  import { createPortal as j } from "react-dom";
4
4
  import { cx as O } from "../../../utils/styles.js";
5
- import { componentPaddingY as K, componentPaddingX as N, iconSizes as S } from "../../../design-system/primitives/sizing.js";
6
5
  import { spacing as C } from "../../../design-system/tokens/spacing.js";
7
- import { durations as X, easings as Y } from "../../../design-system/tokens/motion.js";
6
+ import { iconSizes as S, componentPaddingY as K, componentPaddingX as N } from "../../../design-system/primitives/sizing.js";
8
7
  import { fontSizes as P } from "../../../design-system/tokens/typography.js";
9
- const E = A(null);
8
+ import { durations as X, easings as Y } from "../../../design-system/tokens/motion.js";
9
+ const E = W(null);
10
10
  function B() {
11
11
  return /* @__PURE__ */ o("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ o("path", { d: "M4.5 3l3 3-3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
12
12
  }
@@ -215,7 +215,7 @@ const H = R(function({
215
215
  });
216
216
  H.displayName = "ContextMenu";
217
217
  function Z() {
218
- const a = W(E);
218
+ const a = A(E);
219
219
  if (!a)
220
220
  throw new Error("useContextMenu must be used within a ContextMenu");
221
221
  return a;
@@ -1,12 +1,12 @@
1
- import { jsx as i, jsxs as x } from "react/jsx-runtime";
2
- import { forwardRef as $, createContext as q, useContext as F } from "react";
1
+ import { jsxs as x, jsx as i } from "react/jsx-runtime";
2
+ import { forwardRef as $, useContext as q, createContext as F } from "react";
3
3
  import { cx as I } from "../../../utils/styles.js";
4
4
  import { spacing as t } from "../../../design-system/tokens/spacing.js";
5
5
  import { fontSizes as s } from "../../../design-system/tokens/typography.js";
6
6
  import { durations as z, easings as C } from "../../../design-system/tokens/motion.js";
7
- const L = q(null);
7
+ const L = F(null);
8
8
  function G() {
9
- const u = F(L);
9
+ const u = q(L);
10
10
  if (!u)
11
11
  throw new Error("Step components must be used within a Stepper");
12
12
  return u;
@@ -1,9 +1,9 @@
1
- import { jsx as u, jsxs as N } from "react/jsx-runtime";
2
- import { forwardRef as y, useState as C, useCallback as P, createContext as A, useContext as I } from "react";
1
+ import { jsxs as N, jsx as u } from "react/jsx-runtime";
2
+ import { forwardRef as y, useState as C, useCallback as P, useContext as A, createContext as I } from "react";
3
3
  import { cx as m } from "../../../utils/styles.js";
4
- const w = A(null);
4
+ const w = I(null);
5
5
  function g() {
6
- const i = I(w);
6
+ const i = A(w);
7
7
  if (!i)
8
8
  throw new Error("Tabs components must be used within a Tabs");
9
9
  return i;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./navigation/Tabs/Tabs.cjs"),n=require("./navigation/Accordion/Accordion.cjs"),o=require("./navigation/Dropdown/Dropdown.cjs"),r=require("./navigation/Menu/Menu.cjs"),c=require("./navigation/Pagination/Pagination.cjs"),t=require("./navigation/Breadcrumb/Breadcrumb.cjs"),i=require("./navigation/Stepper/Stepper.cjs"),u=require("./navigation/ContextMenu/ContextMenu.cjs"),d=require("./navigation/SegmentedControl/SegmentedControl.cjs");exports.Tab=e.Tab;exports.TabList=e.TabList;exports.TabPanel=e.TabPanel;exports.TabPanels=e.TabPanels;exports.Tabs=e.Tabs;exports.Accordion=n.Accordion;exports.AccordionContent=n.AccordionContent;exports.AccordionItem=n.AccordionItem;exports.AccordionTrigger=n.AccordionTrigger;exports.Dropdown=o.Dropdown;exports.DropdownDivider=o.DropdownDivider;exports.DropdownItem=o.DropdownItem;exports.DropdownLabel=o.DropdownLabel;exports.Menu=r.Menu;exports.MenuDivider=r.MenuDivider;exports.MenuGroup=r.MenuGroup;exports.MenuItem=r.MenuItem;exports.Pagination=c.Pagination;exports.Breadcrumb=t.Breadcrumb;exports.BreadcrumbItem=t.BreadcrumbItem;exports.Step=i.Step;exports.Stepper=i.Stepper;exports.ContextMenu=u.ContextMenu;exports.useContextMenu=u.useContextMenu;exports.SegmentedControl=d.SegmentedControl;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./navigation/Accordion/Accordion.cjs"),t=require("./navigation/Breadcrumb/Breadcrumb.cjs"),i=require("./navigation/ContextMenu/ContextMenu.cjs"),o=require("./navigation/Dropdown/Dropdown.cjs"),r=require("./navigation/Menu/Menu.cjs"),c=require("./navigation/Pagination/Pagination.cjs"),d=require("./navigation/SegmentedControl/SegmentedControl.cjs"),u=require("./navigation/Stepper/Stepper.cjs"),e=require("./navigation/Tabs/Tabs.cjs");exports.Accordion=n.Accordion;exports.AccordionContent=n.AccordionContent;exports.AccordionItem=n.AccordionItem;exports.AccordionTrigger=n.AccordionTrigger;exports.Breadcrumb=t.Breadcrumb;exports.BreadcrumbItem=t.BreadcrumbItem;exports.ContextMenu=i.ContextMenu;exports.useContextMenu=i.useContextMenu;exports.Dropdown=o.Dropdown;exports.DropdownDivider=o.DropdownDivider;exports.DropdownItem=o.DropdownItem;exports.DropdownLabel=o.DropdownLabel;exports.Menu=r.Menu;exports.MenuDivider=r.MenuDivider;exports.MenuGroup=r.MenuGroup;exports.MenuItem=r.MenuItem;exports.Pagination=c.Pagination;exports.SegmentedControl=d.SegmentedControl;exports.Step=u.Step;exports.Stepper=u.Stepper;exports.Tab=e.Tab;exports.TabList=e.TabList;exports.TabPanel=e.TabPanel;exports.TabPanels=e.TabPanels;exports.Tabs=e.Tabs;
2
2
  //# sourceMappingURL=navigation.cjs.map