@lobehub/ui 6.0.0-beta.2 → 6.0.0-beta.4

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 (80) hide show
  1. package/es/Accordion/style.d.mts +3 -3
  2. package/es/AutoComplete/style.d.mts +1 -1
  3. package/es/Tabs/style.d.mts +1 -1
  4. package/es/Video/Video.mjs +46 -0
  5. package/es/Video/Video.mjs.map +1 -0
  6. package/es/Video/context.mjs +14 -0
  7. package/es/Video/context.mjs.map +1 -0
  8. package/es/Video/index.d.mts +23 -39
  9. package/es/Video/index.mjs +21 -111
  10. package/es/Video/index.mjs.map +1 -1
  11. package/es/Video/parts/Caption.d.mts +9 -0
  12. package/es/Video/parts/Caption.mjs +37 -0
  13. package/es/Video/parts/Caption.mjs.map +1 -0
  14. package/es/Video/parts/CenterPlay.d.mts +8 -0
  15. package/es/Video/parts/CenterPlay.mjs +34 -0
  16. package/es/Video/parts/CenterPlay.mjs.map +1 -0
  17. package/es/Video/parts/Controls.d.mts +9 -0
  18. package/es/Video/parts/Controls.mjs +128 -0
  19. package/es/Video/parts/Controls.mjs.map +1 -0
  20. package/es/Video/parts/Frame.d.mts +9 -0
  21. package/es/Video/parts/Frame.mjs +101 -0
  22. package/es/Video/parts/Frame.mjs.map +1 -0
  23. package/es/Video/parts/HoverPreview.mjs +93 -0
  24. package/es/Video/parts/HoverPreview.mjs.map +1 -0
  25. package/es/Video/parts/LoadError.d.mts +8 -0
  26. package/es/Video/parts/LoadError.mjs +47 -0
  27. package/es/Video/parts/LoadError.mjs.map +1 -0
  28. package/es/Video/parts/PlayPauseIcon.mjs +48 -0
  29. package/es/Video/parts/PlayPauseIcon.mjs.map +1 -0
  30. package/es/Video/parts/RateMenu.mjs +48 -0
  31. package/es/Video/parts/RateMenu.mjs.map +1 -0
  32. package/es/Video/parts/Root.d.mts +9 -0
  33. package/es/Video/parts/Root.mjs +110 -0
  34. package/es/Video/parts/Root.mjs.map +1 -0
  35. package/es/Video/parts/SectionList.d.mts +9 -0
  36. package/es/Video/parts/SectionList.mjs +32 -0
  37. package/es/Video/parts/SectionList.mjs.map +1 -0
  38. package/es/Video/parts/SectionMenu.mjs +63 -0
  39. package/es/Video/parts/SectionMenu.mjs.map +1 -0
  40. package/es/Video/parts/Timeline.d.mts +9 -0
  41. package/es/Video/parts/Timeline.mjs +169 -0
  42. package/es/Video/parts/Timeline.mjs.map +1 -0
  43. package/es/Video/store.mjs +241 -0
  44. package/es/Video/store.mjs.map +1 -0
  45. package/es/Video/style.mjs +393 -23
  46. package/es/Video/style.mjs.map +1 -1
  47. package/es/Video/time.mjs +60 -0
  48. package/es/Video/time.mjs.map +1 -0
  49. package/es/Video/type.d.mts +125 -0
  50. package/es/Video/useControlsIdle.mjs +39 -0
  51. package/es/Video/useControlsIdle.mjs.map +1 -0
  52. package/es/Video/useFullscreen.mjs +17 -0
  53. package/es/Video/useFullscreen.mjs.map +1 -0
  54. package/es/Video/useKeyboard.mjs +60 -0
  55. package/es/Video/useKeyboard.mjs.map +1 -0
  56. package/es/Video/useVideo.d.mts +9 -0
  57. package/es/Video/useVideo.mjs +17 -0
  58. package/es/Video/useVideo.mjs.map +1 -0
  59. package/es/i18n/resources/en/index.d.mts +3 -2
  60. package/es/i18n/resources/en/index.mjs +4 -2
  61. package/es/i18n/resources/en/index.mjs.map +1 -1
  62. package/es/i18n/resources/en/video.d.mts +23 -0
  63. package/es/i18n/resources/en/video.mjs +24 -0
  64. package/es/i18n/resources/en/video.mjs.map +1 -0
  65. package/es/i18n/resources/zhCn/index.d.mts +3 -2
  66. package/es/i18n/resources/zhCn/index.mjs +4 -2
  67. package/es/i18n/resources/zhCn/index.mjs.map +1 -1
  68. package/es/i18n/resources/zhCn/video.d.mts +23 -0
  69. package/es/i18n/resources/zhCn/video.mjs +24 -0
  70. package/es/i18n/resources/zhCn/video.mjs.map +1 -0
  71. package/es/i18n/types.d.mts +2 -1
  72. package/es/index.d.mts +4 -2
  73. package/es/index.mjs +2 -1
  74. package/es/mdx/mdxComponents/Video.d.mts +2 -1
  75. package/es/mdx/mdxComponents/Video.mjs +5 -3
  76. package/es/mdx/mdxComponents/Video.mjs.map +1 -1
  77. package/es/style.css +263 -23
  78. package/package.json +1 -1
  79. package/es/Video/marker.stylex.mjs +0 -9
  80. package/es/Video/marker.stylex.mjs.map +0 -1
@@ -2,13 +2,13 @@ import "@stylexjs/stylex";
2
2
  //#region src/Accordion/style.d.ts
3
3
  export declare const accordionStyles: {
4
4
  panel: string;
5
+ header: string;
5
6
  action: string;
6
7
  content: string;
7
8
  trigger: string;
8
- header: string;
9
- indicator: string;
10
- root: string;
11
9
  item: string;
10
+ root: string;
11
+ indicator: string;
12
12
  itemOutlined: string;
13
13
  rootOutlined: string;
14
14
  actionAlwaysVisible: string;
@@ -42,7 +42,7 @@ declare const styleArrays: {
42
42
  }> | Readonly<{
43
43
  readonly backgroundColor: stylex.StyleXClassNameFor<"backgroundColor", "transparent">;
44
44
  readonly cursor: stylex.StyleXClassNameFor<"cursor", "default">;
45
- readonly display: stylex.StyleXClassNameFor<"display", "flex" | "none">;
45
+ readonly display: stylex.StyleXClassNameFor<"display", "none" | "flex">;
46
46
  }>)[];
47
47
  item: Readonly<{
48
48
  readonly borderRadius: stylex.StyleXClassNameFor<"borderRadius", string>;
@@ -5,8 +5,8 @@ export declare const tabsStyles: {
5
5
  panel: string;
6
6
  tab: string;
7
7
  list: string;
8
- indicator: string;
9
8
  root: string;
9
+ indicator: string;
10
10
  indicatorPoint: string;
11
11
  indicatorRounded: string;
12
12
  indicatorSquare: string;
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { useVideo } from "./useVideo.mjs";
3
+ import Caption from "./parts/Caption.mjs";
4
+ import CenterPlay from "./parts/CenterPlay.mjs";
5
+ import Timeline from "./parts/Timeline.mjs";
6
+ import Controls from "./parts/Controls.mjs";
7
+ import Frame from "./parts/Frame.mjs";
8
+ import LoadError from "./parts/LoadError.mjs";
9
+ import Root from "./parts/Root.mjs";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import clsx from "clsx";
12
+ //#region src/Video/Video.tsx
13
+ const Overlay = ({ render }) => /* @__PURE__ */ jsx(Fragment, { children: render(useVideo()) });
14
+ const Video = ({ className, classNames, frameStep, overlay, style, styles: customStyles, thumbnails = true, ...rest }) => /* @__PURE__ */ jsx(Root, {
15
+ className: clsx(className, classNames?.root),
16
+ style: {
17
+ ...customStyles?.root,
18
+ ...style
19
+ },
20
+ ...rest,
21
+ children: /* @__PURE__ */ jsxs(Frame, {
22
+ className: classNames?.frame,
23
+ style: customStyles?.frame,
24
+ children: [
25
+ overlay && /* @__PURE__ */ jsx(Overlay, { render: overlay }),
26
+ /* @__PURE__ */ jsx(Caption, {}),
27
+ /* @__PURE__ */ jsx(CenterPlay, {}),
28
+ /* @__PURE__ */ jsx(Controls, {
29
+ className: classNames?.controls,
30
+ frameStep,
31
+ style: customStyles?.controls,
32
+ children: /* @__PURE__ */ jsx(Timeline, {
33
+ className: classNames?.timeline,
34
+ style: customStyles?.timeline,
35
+ thumbnails
36
+ })
37
+ }),
38
+ /* @__PURE__ */ jsx(LoadError, {})
39
+ ]
40
+ })
41
+ });
42
+ Video.displayName = "Video";
43
+ //#endregion
44
+ export { Video as default };
45
+
46
+ //# sourceMappingURL=Video.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Video.mjs","names":[],"sources":["../../src/Video/Video.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\n\nimport Caption from './parts/Caption';\nimport CenterPlay from './parts/CenterPlay';\nimport Controls from './parts/Controls';\nimport Frame from './parts/Frame';\nimport LoadError from './parts/LoadError';\nimport Root from './parts/Root';\nimport Timeline from './parts/Timeline';\nimport type { VideoProps, VideoState } from './type';\nimport { useVideo } from './useVideo';\n\nconst Overlay = ({ render }: { render: (state: VideoState) => React.ReactNode }) => (\n <>{render(useVideo())}</>\n);\n\nconst Video = ({\n className,\n classNames,\n frameStep,\n overlay,\n style,\n styles: customStyles,\n thumbnails = true,\n ...rest\n}: VideoProps) => (\n <Root\n className={clsx(className, classNames?.root)}\n style={{ ...customStyles?.root, ...style }}\n {...rest}\n >\n <Frame className={classNames?.frame} style={customStyles?.frame}>\n {overlay && <Overlay render={overlay} />}\n <Caption />\n <CenterPlay />\n <Controls\n className={classNames?.controls}\n frameStep={frameStep}\n style={customStyles?.controls}\n >\n <Timeline\n className={classNames?.timeline}\n style={customStyles?.timeline}\n thumbnails={thumbnails}\n />\n </Controls>\n <LoadError />\n </Frame>\n </Root>\n);\n\nVideo.displayName = 'Video';\n\nexport default Video;\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,WAAW,EAAE,aACjB,oBAAA,UAAA,EAAA,UAAG,OAAO,SAAS,CAAC,EAAI,CAAA;AAG1B,MAAM,SAAS,EACb,WACA,YACA,WACA,SACA,OACA,QAAQ,cACR,aAAa,MACb,GAAG,WAEH,oBAAC,MAAD;CACE,WAAW,KAAK,WAAW,YAAY,IAAI;CAC3C,OAAO;EAAE,GAAG,cAAc;EAAM,GAAG;CAAM;CACzC,GAAI;CAEJ,UAAA,qBAAC,OAAD;EAAO,WAAW,YAAY;EAAO,OAAO,cAAc;EAA1D,UAAA;GACG,WAAW,oBAAC,SAAD,EAAS,QAAQ,QAAU,CAAA;GACvC,oBAAC,SAAD,CAAU,CAAA;GACV,oBAAC,YAAD,CAAa,CAAA;GACb,oBAAC,UAAD;IACE,WAAW,YAAY;IACZ;IACX,OAAO,cAAc;IAErB,UAAA,oBAAC,UAAD;KACE,WAAW,YAAY;KACvB,OAAO,cAAc;KACT;IACb,CAAA;GACO,CAAA;GACV,oBAAC,WAAD,CAAY,CAAA;EACP;;AACH,CAAA;AAGR,MAAM,cAAc"}
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { createContext, use } from "react";
3
+ //#region src/Video/context.ts
4
+ const VideoContext = createContext(null);
5
+ const useVideoContext = () => {
6
+ const value = use(VideoContext);
7
+ if (!value) throw new Error("Video parts must be rendered inside <Video.Root>.");
8
+ return value;
9
+ };
10
+ const FrameContext = createContext(null);
11
+ //#endregion
12
+ export { FrameContext, VideoContext, useVideoContext };
13
+
14
+ //# sourceMappingURL=context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.mjs","names":[],"sources":["../../src/Video/context.ts"],"sourcesContent":["'use client';\n\nimport { createContext, use } from 'react';\n\nimport type { VideoStore } from './store';\nimport type { VideoMarker, VideoMediaProps, VideoSection } from './type';\n\nexport interface VideoConfig {\n fps: number;\n markers: VideoMarker[];\n onMarkerClick?: (marker: VideoMarker) => void;\n onRetry?: () => Promise<unknown> | void;\n playbackRates?: number[];\n sections: VideoSection[];\n}\n\nexport interface VideoContextValue {\n config: VideoConfig;\n media: VideoMediaProps;\n store: VideoStore;\n}\n\nexport const VideoContext = createContext<VideoContextValue | null>(null);\n\nexport const useVideoContext = () => {\n const value = use(VideoContext);\n if (!value) throw new Error('Video parts must be rendered inside <Video.Root>.');\n return value;\n};\n\nexport interface FrameContextValue {\n hold: (held: boolean) => void;\n overlay: boolean;\n setOverlay: (overlay: boolean) => void;\n visible: boolean;\n}\n\nexport const FrameContext = createContext<FrameContextValue | null>(null);\n"],"mappings":";;;AAsBA,MAAa,eAAe,cAAwC,IAAI;AAExE,MAAa,wBAAwB;CACnC,MAAM,QAAQ,IAAI,YAAY;CAC9B,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,mDAAmD;CAC/E,OAAO;AACT;AASA,MAAa,eAAe,cAAwC,IAAI"}
@@ -1,43 +1,27 @@
1
- import { FlexboxProps } from "../Flex/type.mjs";
2
- import "../Flex/index.mjs";
3
- import { VideoProps as VideoProps$1 } from "../types/index.mjs";
4
- import { CSSProperties, Ref } from "react";
1
+ import { VideoCaptionProps, VideoControlsProps, VideoFrameProps, VideoMarker, VideoMarkerColor, VideoMediaProps, VideoPlayer, VideoProps, VideoRootProps, VideoSection, VideoSectionListProps, VideoState, VideoStatus, VideoTimelineProps } from "./type.mjs";
2
+ import Caption from "./parts/Caption.mjs";
3
+ import CenterPlay from "./parts/CenterPlay.mjs";
4
+ import Controls from "./parts/Controls.mjs";
5
+ import Frame from "./parts/Frame.mjs";
6
+ import LoadError from "./parts/LoadError.mjs";
7
+ import Root from "./parts/Root.mjs";
8
+ import SectionList from "./parts/SectionList.mjs";
9
+ import Timeline from "./parts/Timeline.mjs";
10
+ import { useVideo, useVideoPlayer, useVideoState } from "./useVideo.mjs";
11
+ import { ReactNode } from "react";
5
12
  //#region src/Video/index.d.ts
6
- export interface VideoProps extends VideoProps$1, Pick<FlexboxProps, 'width' | 'height'> {
7
- autoPlay?: boolean;
8
- classNames?: {
9
- mask?: string;
10
- video?: string;
11
- wrapper?: string;
12
- };
13
- isLoading?: boolean;
14
- loop?: boolean;
15
- maxHeight?: number | string;
16
- maxWidth?: number | string;
17
- minHeight?: number | string;
18
- minWidth?: number | string;
19
- muted?: HTMLVideoElement['muted'];
20
- onEnded?: VideoProps$1['onEnded'];
21
- onMouseEnter?: VideoProps$1['onMouseEnter'];
22
- onMouseLeave?: VideoProps$1['onMouseLeave'];
23
- onPause?: VideoProps$1['onPause'];
24
- onPlay?: VideoProps$1['onPlay'];
25
- onPlaying?: VideoProps$1['onPlaying'];
26
- onProgress?: VideoProps$1['onProgress'];
27
- poster?: string;
28
- preload?: HTMLVideoElement['preload'];
29
- preview?: boolean;
30
- ref?: Ref<HTMLDivElement>;
31
- size?: number | string;
32
- src: string;
33
- styles?: {
34
- mask?: CSSProperties;
35
- video?: CSSProperties;
36
- wrapper?: CSSProperties;
37
- };
38
- variant?: 'borderless' | 'filled' | 'outlined';
13
+ export interface IVideo {
14
+ (props: VideoProps): ReactNode;
15
+ Caption: typeof Caption;
16
+ CenterPlay: typeof CenterPlay;
17
+ Controls: typeof Controls;
18
+ Frame: typeof Frame;
19
+ LoadError: typeof LoadError;
20
+ Root: typeof Root;
21
+ SectionList: typeof SectionList;
22
+ Timeline: typeof Timeline;
39
23
  }
40
- declare const Video: import("react").NamedExoticComponent<VideoProps>;
24
+ declare const Video: IVideo;
41
25
  //#endregion
42
- export { Video as default };
26
+ export { type VideoCaptionProps, type VideoControlsProps, type VideoFrameProps, type VideoMarker, type VideoMarkerColor, type VideoMediaProps, type VideoPlayer, type VideoProps, type VideoRootProps, type VideoSection, type VideoSectionListProps, type VideoState, type VideoStatus, type VideoTimelineProps, Video as default, useVideo, useVideoPlayer, useVideoState };
43
27
  //# sourceMappingURL=index.d.mts.map
@@ -1,114 +1,24 @@
1
- "use client";
2
- import { styleProps } from "../styles/stylex/props.mjs";
3
- import { cssVar } from "../styles/stylex/cssVar.stylex.mjs";
4
- import FlexBasic_default from "../Flex/FlexBasic.mjs";
5
- import { stylish } from "../styles/stylex/stylish.mjs";
6
- import ActionIcon from "../ActionIcon/ActionIcon.mjs";
7
- import Skeleton from "../Skeleton/index.mjs";
8
- import { videoMarker } from "./marker.stylex.mjs";
9
- import { styles } from "./style.mjs";
10
- import { memo, useMemo, useState } from "react";
11
- import { jsx, jsxs } from "react/jsx-runtime";
12
- import clsx from "clsx";
13
- import { PlayIcon } from "lucide-react";
14
- //#region src/Video/index.tsx
15
- const variantStyles = {
16
- borderless: stylish.variantBorderlessWithoutHover,
17
- filled: styles.filled,
18
- outlined: stylish.variantOutlinedWithoutHover
19
- };
20
- const Video = memo(({ ref, preload = "auto", src, style, classNames, className, maxHeight = "100%", maxWidth = "100%", minHeight, minWidth, onEnded, onPause, onPlay, onPlaying, width, height, onMouseEnter, styles: customStyles, onMouseLeave, preview = true, isLoading, variant = "filled", autoPlay, ...rest }) => {
21
- const [isPlaying, setIsPlaying] = useState(false);
22
- const [showControls, setShowControls] = useState(false);
23
- const cssVariables = useMemo(() => {
24
- const vars = {};
25
- if (maxHeight !== void 0) vars["--video-max-height"] = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
26
- if (maxWidth !== void 0) vars["--video-max-width"] = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
27
- if (minHeight !== void 0) vars["--video-min-height"] = typeof minHeight === "number" ? `${minHeight}px` : minHeight;
28
- if (minWidth !== void 0) vars["--video-min-width"] = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
29
- return vars;
30
- }, [
31
- maxHeight,
32
- maxWidth,
33
- minHeight,
34
- minWidth
35
- ]);
36
- if (isLoading) return /* @__PURE__ */ jsx(Skeleton, {
37
- radius: cssVar.borderRadiusLG,
38
- style: {
39
- height,
40
- maxHeight,
41
- maxWidth,
42
- minHeight,
43
- minWidth,
44
- width
45
- }
46
- });
47
- return /* @__PURE__ */ jsxs(FlexBasic_default, {
48
- height,
49
- ref,
50
- width,
51
- className: styleProps([
52
- styles.root,
53
- variantStyles[variant],
54
- videoMarker
55
- ], clsx(className, classNames?.wrapper)).className,
56
- style: {
57
- ...cssVariables,
58
- ...style,
59
- ...customStyles?.wrapper
60
- },
61
- children: [preview && !isPlaying && /* @__PURE__ */ jsx(FlexBasic_default, {
62
- align: "center",
63
- justify: "center",
64
- ...styleProps(styles.mask, clsx("lobe-video-mask", classNames?.mask), customStyles?.mask),
65
- children: /* @__PURE__ */ jsx(ActionIcon, {
66
- color: "#fff",
67
- icon: PlayIcon,
68
- variant: "filled"
69
- })
70
- }), /* @__PURE__ */ jsx("video", {
71
- autoPlay,
72
- controls: showControls,
73
- height,
74
- preload,
75
- width,
76
- ...styleProps(styles.video, classNames?.video, {
77
- height: "auto",
78
- maxWidth: "100%",
79
- ...customStyles?.video
80
- }),
81
- onEnded: (e) => {
82
- setIsPlaying(false);
83
- onEnded?.(e);
84
- },
85
- onMouseEnter: (e) => {
86
- setShowControls(true);
87
- onMouseEnter?.(e);
88
- },
89
- onMouseLeave: (e) => {
90
- setShowControls(false);
91
- onMouseLeave?.(e);
92
- },
93
- onPause: (e) => {
94
- setIsPlaying(false);
95
- onPause?.(e);
96
- },
97
- onPlay: (e) => {
98
- setIsPlaying(true);
99
- onPlay?.(e);
100
- },
101
- onPlaying: (e) => {
102
- setIsPlaying(true);
103
- onPlaying?.(e);
104
- },
105
- ...rest,
106
- children: /* @__PURE__ */ jsx("source", { src })
107
- })]
108
- });
109
- });
110
- Video.displayName = "Video";
1
+ import { useVideo, useVideoPlayer, useVideoState } from "./useVideo.mjs";
2
+ import Caption from "./parts/Caption.mjs";
3
+ import CenterPlay from "./parts/CenterPlay.mjs";
4
+ import Timeline from "./parts/Timeline.mjs";
5
+ import Controls from "./parts/Controls.mjs";
6
+ import Frame from "./parts/Frame.mjs";
7
+ import LoadError from "./parts/LoadError.mjs";
8
+ import Root from "./parts/Root.mjs";
9
+ import SectionList from "./parts/SectionList.mjs";
10
+ import Video$1 from "./Video.mjs";
11
+ //#region src/Video/index.ts
12
+ const Video = Video$1;
13
+ Video.Caption = Caption;
14
+ Video.CenterPlay = CenterPlay;
15
+ Video.Controls = Controls;
16
+ Video.Frame = Frame;
17
+ Video.LoadError = LoadError;
18
+ Video.Root = Root;
19
+ Video.SectionList = SectionList;
20
+ Video.Timeline = Timeline;
111
21
  //#endregion
112
- export { Video as default };
22
+ export { Video as default, useVideo, useVideoPlayer, useVideoState };
113
23
 
114
24
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Flexbox"],"sources":["../../src/Video/index.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport { PlayIcon } from 'lucide-react';\nimport { type CSSProperties, memo, type Ref, useMemo, useState } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox, type FlexboxProps } from '@/Flex';\nimport Skeleton from '@/Skeleton';\nimport { cssVar } from '@/styles/stylex/cssVar.stylex';\nimport { styleProps } from '@/styles/stylex/props';\nimport { stylish } from '@/styles/stylex/stylish';\nimport { type VideoProps as VProps } from '@/types';\n\nimport { videoMarker } from './marker.stylex';\nimport { maskHoverCls, styles } from './style';\n\nconst variantStyles = {\n borderless: stylish.variantBorderlessWithoutHover,\n filled: styles.filled,\n outlined: stylish.variantOutlinedWithoutHover,\n};\n\nexport interface VideoProps extends VProps, Pick<FlexboxProps, 'width' | 'height'> {\n autoPlay?: boolean;\n classNames?: {\n mask?: string;\n video?: string;\n wrapper?: string;\n };\n isLoading?: boolean;\n loop?: boolean;\n maxHeight?: number | string;\n maxWidth?: number | string;\n minHeight?: number | string;\n minWidth?: number | string;\n muted?: HTMLVideoElement['muted'];\n onEnded?: VProps['onEnded'];\n onMouseEnter?: VProps['onMouseEnter'];\n onMouseLeave?: VProps['onMouseLeave'];\n onPause?: VProps['onPause'];\n onPlay?: VProps['onPlay'];\n onPlaying?: VProps['onPlaying'];\n onProgress?: VProps['onProgress'];\n poster?: string;\n preload?: HTMLVideoElement['preload'];\n preview?: boolean;\n ref?: Ref<HTMLDivElement>;\n size?: number | string;\n src: string;\n styles?: {\n mask?: CSSProperties;\n video?: CSSProperties;\n wrapper?: CSSProperties;\n };\n variant?: 'borderless' | 'filled' | 'outlined';\n}\n\nconst Video = memo<VideoProps>(\n ({\n ref,\n preload = 'auto',\n src,\n style,\n classNames,\n className,\n maxHeight = '100%',\n maxWidth = '100%',\n minHeight,\n minWidth,\n onEnded,\n onPause,\n onPlay,\n onPlaying,\n width,\n height,\n onMouseEnter,\n styles: customStyles,\n onMouseLeave,\n preview = true,\n isLoading,\n variant = 'filled',\n autoPlay,\n ...rest\n }) => {\n const [isPlaying, setIsPlaying] = useState(false);\n const [showControls, setShowControls] = useState(false);\n\n // Convert props to CSS variables\n const cssVariables = useMemo<Record<string, string>>(() => {\n const vars: Record<string, string> = {};\n if (maxHeight !== undefined) {\n vars['--video-max-height'] = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight;\n }\n if (maxWidth !== undefined) {\n vars['--video-max-width'] = typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth;\n }\n if (minHeight !== undefined) {\n vars['--video-min-height'] = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n }\n if (minWidth !== undefined) {\n vars['--video-min-width'] = typeof minWidth === 'number' ? `${minWidth}px` : minWidth;\n }\n return vars;\n }, [maxHeight, maxWidth, minHeight, minWidth]);\n\n if (isLoading)\n return (\n <Skeleton\n radius={cssVar.borderRadiusLG}\n style={{\n height,\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n width,\n }}\n />\n );\n\n return (\n <Flexbox\n height={height}\n ref={ref}\n width={width}\n className={\n styleProps(\n [styles.root, variantStyles[variant], videoMarker],\n clsx(className, classNames?.wrapper),\n ).className\n }\n style={{\n ...cssVariables,\n ...style,\n ...customStyles?.wrapper,\n }}\n >\n {preview && !isPlaying && (\n <Flexbox\n align={'center'}\n justify={'center'}\n {...styleProps(styles.mask, clsx(maskHoverCls, classNames?.mask), customStyles?.mask)}\n >\n <ActionIcon color={'#fff'} icon={PlayIcon} variant={'filled'} />\n </Flexbox>\n )}\n <video\n autoPlay={autoPlay}\n controls={showControls}\n height={height}\n preload={preload}\n width={width}\n {...styleProps(styles.video, classNames?.video, {\n height: 'auto',\n maxWidth: '100%',\n ...customStyles?.video,\n })}\n onEnded={(e) => {\n setIsPlaying(false);\n onEnded?.(e);\n }}\n onMouseEnter={(e) => {\n setShowControls(true);\n onMouseEnter?.(e);\n }}\n onMouseLeave={(e) => {\n setShowControls(false);\n onMouseLeave?.(e);\n }}\n onPause={(e) => {\n setIsPlaying(false);\n onPause?.(e);\n }}\n onPlay={(e) => {\n setIsPlaying(true);\n onPlay?.(e);\n }}\n onPlaying={(e) => {\n setIsPlaying(true);\n onPlaying?.(e);\n }}\n {...rest}\n >\n <source src={src} />\n </video>\n </Flexbox>\n );\n },\n);\n\nVideo.displayName = 'Video';\n\nexport default Video;\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,gBAAgB;CACpB,YAAY,QAAQ;CACpB,QAAQ,OAAO;CACf,UAAU,QAAQ;AACpB;AAqCA,MAAM,QAAQ,MACX,EACC,KACA,UAAU,QACV,KACA,OACA,YACA,WACA,YAAY,QACZ,WAAW,QACX,WACA,UACA,SACA,SACA,QACA,WACA,OACA,QACA,cACA,QAAQ,cACR,cACA,UAAU,MACV,WACA,UAAU,UACV,UACA,GAAG,WACC;CACJ,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CAGtD,MAAM,eAAe,cAAsC;EACzD,MAAM,OAA+B,CAAC;EACtC,IAAI,cAAc,KAAA,GAChB,KAAK,wBAAwB,OAAO,cAAc,WAAW,GAAG,UAAU,MAAM;EAElF,IAAI,aAAa,KAAA,GACf,KAAK,uBAAuB,OAAO,aAAa,WAAW,GAAG,SAAS,MAAM;EAE/E,IAAI,cAAc,KAAA,GAChB,KAAK,wBAAwB,OAAO,cAAc,WAAW,GAAG,UAAU,MAAM;EAElF,IAAI,aAAa,KAAA,GACf,KAAK,uBAAuB,OAAO,aAAa,WAAW,GAAG,SAAS,MAAM;EAE/E,OAAO;CACT,GAAG;EAAC;EAAW;EAAU;EAAW;CAAQ,CAAC;CAE7C,IAAI,WACF,OACE,oBAAC,UAAD;EACE,QAAQ,OAAO;EACf,OAAO;GACL;GACA;GACA;GACA;GACA;GACA;EACF;CACD,CAAA;CAGL,OACE,qBAACA,mBAAD;EACU;EACH;EACE;EACP,WACE,WACE;GAAC,OAAO;GAAM,cAAc;GAAU;EAAW,GACjD,KAAK,WAAW,YAAY,OAAO,CACrC,CAAC,CAAC;EAEJ,OAAO;GACL,GAAG;GACH,GAAG;GACH,GAAG,cAAc;EACnB;EAdF,UAAA,CAgBG,WAAW,CAAC,aACX,oBAACA,mBAAD;GACE,OAAO;GACP,SAAS;GACT,GAAI,WAAW,OAAO,MAAM,KAAA,mBAAmB,YAAY,IAAI,GAAG,cAAc,IAAI;GAEpF,UAAA,oBAAC,YAAD;IAAY,OAAO;IAAQ,MAAM;IAAU,SAAS;GAAW,CAAA;EACxD,CAAA,GAEX,oBAAC,SAAD;GACY;GACV,UAAU;GACF;GACC;GACF;GACP,GAAI,WAAW,OAAO,OAAO,YAAY,OAAO;IAC9C,QAAQ;IACR,UAAU;IACV,GAAG,cAAc;GACnB,CAAC;GACD,UAAU,MAAM;IACd,aAAa,KAAK;IAClB,UAAU,CAAC;GACb;GACA,eAAe,MAAM;IACnB,gBAAgB,IAAI;IACpB,eAAe,CAAC;GAClB;GACA,eAAe,MAAM;IACnB,gBAAgB,KAAK;IACrB,eAAe,CAAC;GAClB;GACA,UAAU,MAAM;IACd,aAAa,KAAK;IAClB,UAAU,CAAC;GACb;GACA,SAAS,MAAM;IACb,aAAa,IAAI;IACjB,SAAS,CAAC;GACZ;GACA,YAAY,MAAM;IAChB,aAAa,IAAI;IACjB,YAAY,CAAC;GACf;GACA,GAAI;GAEJ,UAAA,oBAAC,UAAD,EAAa,IAAM,CAAA;EACd,CAAA,CACA;;AAEb,CACF;AAEA,MAAM,cAAc"}
1
+ {"version":3,"file":"index.mjs","names":["VideoPreset"],"sources":["../../src/Video/index.ts"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport Caption from './parts/Caption';\nimport CenterPlay from './parts/CenterPlay';\nimport Controls from './parts/Controls';\nimport Frame from './parts/Frame';\nimport LoadError from './parts/LoadError';\nimport Root from './parts/Root';\nimport SectionList from './parts/SectionList';\nimport Timeline from './parts/Timeline';\nimport type { VideoProps } from './type';\nimport VideoPreset from './Video';\n\nexport interface IVideo {\n (props: VideoProps): ReactNode;\n Caption: typeof Caption;\n CenterPlay: typeof CenterPlay;\n Controls: typeof Controls;\n Frame: typeof Frame;\n LoadError: typeof LoadError;\n Root: typeof Root;\n SectionList: typeof SectionList;\n Timeline: typeof Timeline;\n}\n\nconst Video = VideoPreset as unknown as IVideo;\nVideo.Caption = Caption;\nVideo.CenterPlay = CenterPlay;\nVideo.Controls = Controls;\nVideo.Frame = Frame;\nVideo.LoadError = LoadError;\nVideo.Root = Root;\nVideo.SectionList = SectionList;\nVideo.Timeline = Timeline;\n\nexport default Video;\nexport type * from './type';\nexport { useVideo, useVideoPlayer, useVideoState } from './useVideo';\n"],"mappings":";;;;;;;;;;;AAyBA,MAAM,QAAQA;AACd,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,QAAQ;AACd,MAAM,YAAY;AAClB,MAAM,OAAO;AACb,MAAM,cAAc;AACpB,MAAM,WAAW"}
@@ -0,0 +1,9 @@
1
+ import { VideoCaptionProps } from "../type.mjs";
2
+ //#region src/Video/parts/Caption.d.ts
3
+ declare const Caption: {
4
+ ({ action, className, style }: VideoCaptionProps): import("react").JSX.Element | null;
5
+ displayName: string;
6
+ };
7
+ //#endregion
8
+ export { Caption as default };
9
+ //# sourceMappingURL=Caption.d.mts.map
@@ -0,0 +1,37 @@
1
+ "use client";
2
+ import { styleProps } from "../../styles/stylex/props.mjs";
3
+ import { FrameContext } from "../context.mjs";
4
+ import { markerColor, styles } from "../style.mjs";
5
+ import { useVideo } from "../useVideo.mjs";
6
+ import { use } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/Video/parts/Caption.tsx
9
+ const Caption = ({ action, className, style }) => {
10
+ const frame = use(FrameContext);
11
+ const markers = useVideo((state) => state.captions ? state.activeMarkers : void 0);
12
+ if (!markers || markers.length === 0) return null;
13
+ const raised = Boolean(frame?.overlay && frame.visible);
14
+ return /* @__PURE__ */ jsx("div", {
15
+ "data-raised": String(raised),
16
+ "data-video-caption": "",
17
+ ...styleProps([styles.caption, raised && styles.captionRaised], className, style),
18
+ onClick: (event) => event.stopPropagation(),
19
+ onPointerDown: (event) => event.stopPropagation(),
20
+ children: markers.map((marker, index) => /* @__PURE__ */ jsxs("div", {
21
+ ...styleProps(styles.captionItem),
22
+ children: [(marker.label !== void 0 || action) && /* @__PURE__ */ jsxs("div", {
23
+ ...styleProps(styles.captionTitle),
24
+ children: [
25
+ /* @__PURE__ */ jsx("span", { ...styleProps(styles.dot, void 0, { background: markerColor(marker.color) }) }),
26
+ marker.label,
27
+ action?.(marker)
28
+ ]
29
+ }), /* @__PURE__ */ jsx("div", { children: marker.content })]
30
+ }, marker.key ?? `${marker.time}-${index}`))
31
+ });
32
+ };
33
+ Caption.displayName = "VideoCaption";
34
+ //#endregion
35
+ export { Caption as default };
36
+
37
+ //# sourceMappingURL=Caption.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Caption.mjs","names":[],"sources":["../../../src/Video/parts/Caption.tsx"],"sourcesContent":["'use client';\n\nimport { use } from 'react';\n\nimport { styleProps } from '@/styles/stylex/props';\n\nimport { FrameContext } from '../context';\nimport { markerColor, styles } from '../style';\nimport type { VideoCaptionProps } from '../type';\nimport { useVideo } from '../useVideo';\n\nconst Caption = ({ action, className, style }: VideoCaptionProps) => {\n const frame = use(FrameContext);\n const markers = useVideo((state) => (state.captions ? state.activeMarkers : undefined));\n if (!markers || markers.length === 0) return null;\n const raised = Boolean(frame?.overlay && frame.visible);\n\n return (\n <div\n data-raised={String(raised)}\n data-video-caption=\"\"\n {...styleProps([styles.caption, raised && styles.captionRaised], className, style)}\n onClick={(event) => event.stopPropagation()}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {markers.map((marker, index) => (\n <div key={marker.key ?? `${marker.time}-${index}`} {...styleProps(styles.captionItem)}>\n {(marker.label !== undefined || action) && (\n <div {...styleProps(styles.captionTitle)}>\n <span\n {...styleProps(styles.dot, undefined, { background: markerColor(marker.color) })}\n />\n {marker.label}\n {action?.(marker)}\n </div>\n )}\n <div>{marker.content}</div>\n </div>\n ))}\n </div>\n );\n};\n\nCaption.displayName = 'VideoCaption';\n\nexport default Caption;\n"],"mappings":";;;;;;;;AAWA,MAAM,WAAW,EAAE,QAAQ,WAAW,YAA+B;CACnE,MAAM,QAAQ,IAAI,YAAY;CAC9B,MAAM,UAAU,UAAU,UAAW,MAAM,WAAW,MAAM,gBAAgB,KAAA,CAAU;CACtF,IAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,OAAO;CAC7C,MAAM,SAAS,QAAQ,OAAO,WAAW,MAAM,OAAO;CAEtD,OACE,oBAAC,OAAD;EACE,eAAa,OAAO,MAAM;EAC1B,sBAAmB;EACnB,GAAI,WAAW,CAAC,OAAO,SAAS,UAAU,OAAO,aAAa,GAAG,WAAW,KAAK;EACjF,UAAU,UAAU,MAAM,gBAAgB;EAC1C,gBAAgB,UAAU,MAAM,gBAAgB;EAE/C,UAAA,QAAQ,KAAK,QAAQ,UACpB,qBAAC,OAAD;GAAmD,GAAI,WAAW,OAAO,WAAW;GAApF,UAAA,EACI,OAAO,UAAU,KAAA,KAAa,WAC9B,qBAAC,OAAD;IAAK,GAAI,WAAW,OAAO,YAAY;IAAvC,UAAA;KACE,oBAAC,QAAD,EACE,GAAI,WAAW,OAAO,KAAK,KAAA,GAAW,EAAE,YAAY,YAAY,OAAO,KAAK,EAAE,CAAC,EAChF,CAAA;KACA,OAAO;KACP,SAAS,MAAM;IACb;GAEP,CAAA,GAAA,oBAAC,OAAD,EAAA,UAAM,OAAO,QAAa,CAAA,CACvB;EAXK,GAAA,OAAO,OAAO,GAAG,OAAO,KAAK,GAAG,OAWrC,CACN;CACE,CAAA;AAET;AAEA,QAAQ,cAAc"}
@@ -0,0 +1,8 @@
1
+ //#region src/Video/parts/CenterPlay.d.ts
2
+ declare const CenterPlay: {
3
+ (): import("react").JSX.Element | null;
4
+ displayName: string;
5
+ };
6
+ //#endregion
7
+ export { CenterPlay as default };
8
+ //# sourceMappingURL=CenterPlay.d.mts.map
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { styleProps } from "../../styles/stylex/props.mjs";
3
+ import { useTranslation } from "../../i18n/useTranslation.mjs";
4
+ import { useVideoContext } from "../context.mjs";
5
+ import { styles } from "../style.mjs";
6
+ import { useVideo } from "../useVideo.mjs";
7
+ import video_default from "../../i18n/resources/en/video.mjs";
8
+ import { jsx } from "react/jsx-runtime";
9
+ import { Play } from "lucide-react";
10
+ //#region src/Video/parts/CenterPlay.tsx
11
+ const CenterPlay = () => {
12
+ const { store } = useVideoContext();
13
+ const { t } = useTranslation(video_default);
14
+ if (!useVideo((state) => state.paused && state.status === "ready" && state.time < .05)) return null;
15
+ return /* @__PURE__ */ jsx("button", {
16
+ "aria-label": t("video.play"),
17
+ type: "button",
18
+ ...styleProps(styles.centerPlay),
19
+ onClick: (event) => {
20
+ event.stopPropagation();
21
+ store.play();
22
+ },
23
+ children: /* @__PURE__ */ jsx(Play, {
24
+ fill: "currentColor",
25
+ size: 24,
26
+ strokeWidth: 0
27
+ })
28
+ });
29
+ };
30
+ CenterPlay.displayName = "VideoCenterPlay";
31
+ //#endregion
32
+ export { CenterPlay as default };
33
+
34
+ //# sourceMappingURL=CenterPlay.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CenterPlay.mjs","names":["videoMessages"],"sources":["../../../src/Video/parts/CenterPlay.tsx"],"sourcesContent":["'use client';\n\nimport { Play } from 'lucide-react';\n\nimport videoMessages from '@/i18n/resources/en/video';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport { styleProps } from '@/styles/stylex/props';\n\nimport { useVideoContext } from '../context';\nimport { styles } from '../style';\nimport { useVideo } from '../useVideo';\n\nconst CenterPlay = () => {\n const { store } = useVideoContext();\n const { t } = useTranslation(videoMessages);\n const show = useVideo((state) => state.paused && state.status === 'ready' && state.time < 0.05);\n if (!show) return null;\n\n return (\n <button\n aria-label={t('video.play')}\n type=\"button\"\n {...styleProps(styles.centerPlay)}\n onClick={(event) => {\n event.stopPropagation();\n void store.play();\n }}\n >\n <Play fill=\"currentColor\" size={24} strokeWidth={0} />\n </button>\n );\n};\n\nCenterPlay.displayName = 'VideoCenterPlay';\n\nexport default CenterPlay;\n"],"mappings":";;;;;;;;;;AAYA,MAAM,mBAAmB;CACvB,MAAM,EAAE,UAAU,gBAAgB;CAClC,MAAM,EAAE,MAAM,eAAeA,aAAa;CAE1C,IAAI,CADS,UAAU,UAAU,MAAM,UAAU,MAAM,WAAW,WAAW,MAAM,OAAO,GAClF,GAAG,OAAO;CAElB,OACE,oBAAC,UAAD;EACE,cAAY,EAAE,YAAY;EAC1B,MAAK;EACL,GAAI,WAAW,OAAO,UAAU;EAChC,UAAU,UAAU;GAClB,MAAM,gBAAgB;GACtB,MAAW,KAAK;EAClB;EAEA,UAAA,oBAAC,MAAD;GAAM,MAAK;GAAe,MAAM;GAAI,aAAa;EAAI,CAAA;CAC/C,CAAA;AAEZ;AAEA,WAAW,cAAc"}
@@ -0,0 +1,9 @@
1
+ import { VideoControlsProps } from "../type.mjs";
2
+ //#region src/Video/parts/Controls.d.ts
3
+ declare const Controls: {
4
+ ({ children, className, extra, frameStep, style }: VideoControlsProps): import("react").JSX.Element;
5
+ displayName: string;
6
+ };
7
+ //#endregion
8
+ export { Controls as default };
9
+ //# sourceMappingURL=Controls.d.mts.map
@@ -0,0 +1,128 @@
1
+ "use client";
2
+ import { styleProps } from "../../styles/stylex/props.mjs";
3
+ import { useTranslation } from "../../i18n/useTranslation.mjs";
4
+ import { FrameContext, useVideoContext } from "../context.mjs";
5
+ import { styles } from "../style.mjs";
6
+ import { formatTime, frameOf } from "../time.mjs";
7
+ import { useVideo } from "../useVideo.mjs";
8
+ import video_default from "../../i18n/resources/en/video.mjs";
9
+ import { useFullscreen } from "../useFullscreen.mjs";
10
+ import PlayPauseIcon from "./PlayPauseIcon.mjs";
11
+ import RateMenu from "./RateMenu.mjs";
12
+ import SectionMenu from "./SectionMenu.mjs";
13
+ import Timeline from "./Timeline.mjs";
14
+ import { use, useLayoutEffect } from "react";
15
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
+ import { Captions, ChevronLeft, ChevronRight, Maximize, Minimize, Volume2, VolumeX } from "lucide-react";
17
+ //#region src/Video/parts/Controls.tsx
18
+ const BarButton = ({ active, children, label, onClick, pressed, shortcut }) => /* @__PURE__ */ jsx("button", {
19
+ "aria-label": label,
20
+ "aria-pressed": pressed,
21
+ title: shortcut ? `${label} (${shortcut})` : label,
22
+ type: "button",
23
+ ...styleProps([styles.barButton, active && styles.barButtonActive]),
24
+ onClick,
25
+ children
26
+ });
27
+ const TimeReadout = () => {
28
+ const seconds = useVideo((state) => Math.floor(state.time));
29
+ const duration = useVideo((state) => state.duration);
30
+ return /* @__PURE__ */ jsx("span", {
31
+ ...styleProps(styles.time, void 0, { marginInline: 6 }),
32
+ children: `${formatTime(seconds)} / ${formatTime(duration)}`
33
+ });
34
+ };
35
+ const FrameReadout = () => {
36
+ const { config } = useVideoContext();
37
+ const { t } = useTranslation(video_default);
38
+ const frame = useVideo((state) => frameOf(state.time, config.fps));
39
+ return /* @__PURE__ */ jsx("span", {
40
+ ...styleProps(styles.frameNo, void 0, { marginInlineEnd: 6 }),
41
+ children: `${t("video.frame")} ${frame}`
42
+ });
43
+ };
44
+ const Controls = ({ children, className, extra, frameStep, style }) => {
45
+ const { config, store } = useVideoContext();
46
+ const frame = use(FrameContext);
47
+ const { t } = useTranslation(video_default);
48
+ const paused = useVideo((state) => state.paused);
49
+ const muted = useVideo((state) => state.muted);
50
+ const captions = useVideo((state) => state.captions);
51
+ const ready = useVideo((state) => state.status === "ready");
52
+ const fullscreen = useFullscreen(store);
53
+ const overlay = frame !== null;
54
+ useLayoutEffect(() => {
55
+ if (!frame) return;
56
+ frame.setOverlay(true);
57
+ return () => frame.setOverlay(false);
58
+ }, [frame?.setOverlay]);
59
+ const visible = !overlay || frame.visible;
60
+ const hasCaptions = config.markers.some((marker) => marker.content !== void 0 && marker.content !== null);
61
+ return /* @__PURE__ */ jsx("div", {
62
+ "data-video-controls": "",
63
+ "data-visible": String(visible),
64
+ ...styleProps([
65
+ styles.controls,
66
+ overlay ? styles.controlsOverlay : styles.controlsBelow,
67
+ overlay && !visible && styles.controlsHidden
68
+ ], className, style),
69
+ onClick: (event) => event.stopPropagation(),
70
+ onDoubleClick: (event) => event.stopPropagation(),
71
+ children: /* @__PURE__ */ jsxs("div", {
72
+ ...styleProps(!ready && styles.disabled),
73
+ children: [children ?? /* @__PURE__ */ jsx(Timeline, {}), /* @__PURE__ */ jsxs("div", {
74
+ ...styleProps(styles.row),
75
+ children: [
76
+ /* @__PURE__ */ jsx(BarButton, {
77
+ label: paused ? t("video.play") : t("video.pause"),
78
+ shortcut: "K",
79
+ onClick: store.toggle,
80
+ children: /* @__PURE__ */ jsx(PlayPauseIcon, { paused })
81
+ }),
82
+ /* @__PURE__ */ jsx(BarButton, {
83
+ label: muted ? t("video.unmute") : t("video.mute"),
84
+ shortcut: "M",
85
+ onClick: store.toggleMute,
86
+ children: muted ? /* @__PURE__ */ jsx(VolumeX, { size: 16 }) : /* @__PURE__ */ jsx(Volume2, { size: 16 })
87
+ }),
88
+ frameStep && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(BarButton, {
89
+ label: t("video.previousFrame"),
90
+ shortcut: ",",
91
+ onClick: () => store.step(-1),
92
+ children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 })
93
+ }), /* @__PURE__ */ jsx(BarButton, {
94
+ label: t("video.nextFrame"),
95
+ shortcut: ".",
96
+ onClick: () => store.step(1),
97
+ children: /* @__PURE__ */ jsx(ChevronRight, { size: 16 })
98
+ })] }),
99
+ /* @__PURE__ */ jsx(TimeReadout, {}),
100
+ frameStep && /* @__PURE__ */ jsx(FrameReadout, {}),
101
+ /* @__PURE__ */ jsx(SectionMenu, {}),
102
+ /* @__PURE__ */ jsx("div", { ...styleProps(styles.spacer) }),
103
+ extra,
104
+ hasCaptions && /* @__PURE__ */ jsx(BarButton, {
105
+ active: captions,
106
+ label: captions ? t("video.captionsHide") : t("video.captionsShow"),
107
+ pressed: captions,
108
+ shortcut: "C",
109
+ onClick: () => store.setCaptions(!captions),
110
+ children: /* @__PURE__ */ jsx(Captions, { size: 16 })
111
+ }),
112
+ /* @__PURE__ */ jsx(RateMenu, {}),
113
+ /* @__PURE__ */ jsx(BarButton, {
114
+ label: fullscreen ? t("video.exitFullscreen") : t("video.fullscreen"),
115
+ shortcut: "F",
116
+ onClick: store.toggleFullscreen,
117
+ children: fullscreen ? /* @__PURE__ */ jsx(Minimize, { size: 15 }) : /* @__PURE__ */ jsx(Maximize, { size: 15 })
118
+ })
119
+ ]
120
+ })]
121
+ })
122
+ });
123
+ };
124
+ Controls.displayName = "VideoControls";
125
+ //#endregion
126
+ export { Controls as default };
127
+
128
+ //# sourceMappingURL=Controls.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Controls.mjs","names":["videoMessages"],"sources":["../../../src/Video/parts/Controls.tsx"],"sourcesContent":["'use client';\n\nimport {\n Captions,\n ChevronLeft,\n ChevronRight,\n Maximize,\n Minimize,\n Volume2,\n VolumeX,\n} from 'lucide-react';\nimport { type ReactNode, use, useLayoutEffect } from 'react';\n\nimport videoMessages from '@/i18n/resources/en/video';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport { styleProps } from '@/styles/stylex/props';\n\nimport { FrameContext, useVideoContext } from '../context';\nimport { styles } from '../style';\nimport { formatTime, frameOf } from '../time';\nimport type { VideoControlsProps } from '../type';\nimport { useFullscreen } from '../useFullscreen';\nimport { useVideo } from '../useVideo';\nimport PlayPauseIcon from './PlayPauseIcon';\nimport RateMenu from './RateMenu';\nimport SectionMenu from './SectionMenu';\nimport Timeline from './Timeline';\n\nconst BarButton = ({\n active,\n children,\n label,\n onClick,\n pressed,\n shortcut,\n}: {\n active?: boolean;\n children: ReactNode;\n label: string;\n onClick: () => void;\n pressed?: boolean;\n shortcut?: string;\n}) => (\n <button\n aria-label={label}\n aria-pressed={pressed}\n title={shortcut ? `${label} (${shortcut})` : label}\n type=\"button\"\n {...styleProps([styles.barButton, active && styles.barButtonActive])}\n onClick={onClick}\n >\n {children}\n </button>\n);\n\n// Leaves so playback re-renders only these, and the clock only once a second.\nconst TimeReadout = () => {\n const seconds = useVideo((state) => Math.floor(state.time));\n const duration = useVideo((state) => state.duration);\n return (\n <span {...styleProps(styles.time, undefined, { marginInline: 6 })}>\n {`${formatTime(seconds)} / ${formatTime(duration)}`}\n </span>\n );\n};\n\nconst FrameReadout = () => {\n const { config } = useVideoContext();\n const { t } = useTranslation(videoMessages);\n const frame = useVideo((state) => frameOf(state.time, config.fps));\n return (\n <span {...styleProps(styles.frameNo, undefined, { marginInlineEnd: 6 })}>\n {`${t('video.frame')} ${frame}`}\n </span>\n );\n};\n\nconst Controls = ({ children, className, extra, frameStep, style }: VideoControlsProps) => {\n const { config, store } = useVideoContext();\n const frame = use(FrameContext);\n const { t } = useTranslation(videoMessages);\n const paused = useVideo((state) => state.paused);\n const muted = useVideo((state) => state.muted);\n const captions = useVideo((state) => state.captions);\n const ready = useVideo((state) => state.status === 'ready');\n const fullscreen = useFullscreen(store);\n const overlay = frame !== null;\n\n useLayoutEffect(() => {\n if (!frame) return;\n frame.setOverlay(true);\n return () => frame.setOverlay(false);\n }, [frame?.setOverlay]);\n const visible = !overlay || frame.visible;\n const hasCaptions = config.markers.some(\n (marker) => marker.content !== undefined && marker.content !== null,\n );\n\n return (\n <div\n data-video-controls=\"\"\n data-visible={String(visible)}\n {...styleProps(\n [\n styles.controls,\n overlay ? styles.controlsOverlay : styles.controlsBelow,\n overlay && !visible && styles.controlsHidden,\n ],\n className,\n style,\n )}\n onClick={(event) => event.stopPropagation()}\n onDoubleClick={(event) => event.stopPropagation()}\n >\n <div {...styleProps(!ready && styles.disabled)}>\n {children ?? <Timeline />}\n <div {...styleProps(styles.row)}>\n <BarButton\n label={paused ? t('video.play') : t('video.pause')}\n shortcut=\"K\"\n onClick={store.toggle}\n >\n <PlayPauseIcon paused={paused} />\n </BarButton>\n <BarButton\n label={muted ? t('video.unmute') : t('video.mute')}\n shortcut=\"M\"\n onClick={store.toggleMute}\n >\n {muted ? <VolumeX size={16} /> : <Volume2 size={16} />}\n </BarButton>\n {frameStep && (\n <>\n <BarButton\n label={t('video.previousFrame')}\n shortcut=\",\"\n onClick={() => store.step(-1)}\n >\n <ChevronLeft size={16} />\n </BarButton>\n <BarButton label={t('video.nextFrame')} shortcut=\".\" onClick={() => store.step(1)}>\n <ChevronRight size={16} />\n </BarButton>\n </>\n )}\n <TimeReadout />\n {frameStep && <FrameReadout />}\n <SectionMenu />\n <div {...styleProps(styles.spacer)} />\n {extra}\n {hasCaptions && (\n <BarButton\n active={captions}\n label={captions ? t('video.captionsHide') : t('video.captionsShow')}\n pressed={captions}\n shortcut=\"C\"\n onClick={() => store.setCaptions(!captions)}\n >\n <Captions size={16} />\n </BarButton>\n )}\n <RateMenu />\n <BarButton\n label={fullscreen ? t('video.exitFullscreen') : t('video.fullscreen')}\n shortcut=\"F\"\n onClick={store.toggleFullscreen}\n >\n {fullscreen ? <Minimize size={15} /> : <Maximize size={15} />}\n </BarButton>\n </div>\n </div>\n </div>\n );\n};\n\nControls.displayName = 'VideoControls';\n\nexport default Controls;\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { VideoFrameProps } from "../type.mjs";
2
+ //#region src/Video/parts/Frame.d.ts
3
+ declare const Frame: {
4
+ ({ children, className, style }: VideoFrameProps): import("react").JSX.Element;
5
+ displayName: string;
6
+ };
7
+ //#endregion
8
+ export { Frame as default };
9
+ //# sourceMappingURL=Frame.d.mts.map