@design-edito/tools 0.3.10 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agnostic/arrays/index.d.ts +1 -1
- package/agnostic/arrays/index.js +1 -1
- package/agnostic/colors/index.d.ts +2 -2
- package/agnostic/colors/index.js +2 -2
- package/agnostic/css/clss/index.d.ts +53 -1
- package/agnostic/css/clss/index.js +1 -1
- package/agnostic/css/index.d.ts +2 -2
- package/agnostic/css/index.js +2 -2
- package/agnostic/errors/index.d.ts +1 -1
- package/agnostic/errors/index.js +1 -1
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +20 -20
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +20 -20
- package/agnostic/html/hyper-json/smart-tags/isolated/index.d.ts +4 -4
- package/agnostic/html/hyper-json/smart-tags/isolated/index.js +4 -4
- package/agnostic/index.d.ts +4 -4
- package/agnostic/index.js +4 -4
- package/agnostic/misc/assert/index.d.ts +3 -0
- package/agnostic/misc/crossenv/index.d.ts +1 -1
- package/agnostic/misc/crossenv/index.js +1 -1
- package/agnostic/misc/index.d.ts +5 -5
- package/agnostic/misc/index.js +5 -5
- package/agnostic/misc/logs/index.d.ts +1 -1
- package/agnostic/misc/logs/index.js +1 -1
- package/agnostic/misc/logs/logger/index.d.ts +10 -0
- package/agnostic/misc/logs/logger/index.js +40 -10
- package/agnostic/misc/logs/styles/index.d.ts +1 -0
- package/agnostic/misc/logs/styles/index.js +27 -9
- package/agnostic/numbers/index.d.ts +2 -2
- package/agnostic/numbers/index.js +2 -2
- package/agnostic/objects/index.d.ts +4 -4
- package/agnostic/objects/index.js +4 -4
- package/agnostic/sanitization/index.d.ts +1 -1
- package/agnostic/sanitization/index.js +1 -1
- package/agnostic/strings/index.d.ts +1 -1
- package/agnostic/strings/index.js +1 -1
- package/agnostic/time/index.d.ts +2 -2
- package/agnostic/time/index.js +2 -2
- package/agnostic/time/transitions/index.d.ts +3 -3
- package/agnostic/time/transitions/index.js +4 -4
- package/components/Disclaimer/index.d.ts +45 -0
- package/components/Disclaimer/index.js +70 -0
- package/components/Drawer/index.d.ts +45 -0
- package/components/Drawer/index.js +82 -0
- package/components/Drawer/styles.module.css +0 -0
- package/components/EventListener/index.d.ts +20 -3
- package/components/EventListener/index.js +15 -22
- package/components/Gallery/index.d.ts +67 -0
- package/components/Gallery/index.js +173 -0
- package/components/Gallery/styles.module.css +33 -0
- package/components/Gallery/utils.d.ts +1 -0
- package/components/Image/index.d.ts +60 -0
- package/components/Image/index.js +99 -0
- package/components/Image/styles.module.css +0 -0
- package/components/IntersectionObserver/index.d.ts +48 -11
- package/components/IntersectionObserver/index.js +13 -22
- package/components/Paginator/index.d.ts +72 -0
- package/components/Paginator/index.js +116 -0
- package/components/Paginator/styles.module.css +9 -0
- package/components/ResizeObserver/index.d.ts +27 -0
- package/components/ResizeObserver/index.js +81 -0
- package/components/Scrllgngn/index.d.ts +123 -0
- package/components/Scrllgngn/index.js +175 -0
- package/components/Scrllgngn/styles.module.css +74 -0
- package/components/Sequencer/index.controlled.d.ts +78 -0
- package/components/Sequencer/index.d.ts +85 -0
- package/components/Sequencer/index.js +109 -0
- package/components/Sequencer/styles.module.css +0 -0
- package/components/ShadowRoot/index.d.ts +35 -0
- package/components/ShadowRoot/index.js +56 -0
- package/components/ShadowRoot/styles.module.css +0 -0
- package/components/Subtitles/index.d.ts +58 -0
- package/components/Subtitles/index.js +111 -0
- package/components/Subtitles/styles.module.css +0 -0
- package/components/Subtitles/types.d.ts +10 -0
- package/components/Subtitles/types.js +0 -0
- package/components/Subtitles/utils.d.ts +28 -0
- package/components/Theatre/index.d.ts +64 -0
- package/components/Theatre/index.js +97 -0
- package/components/Theatre/styles.module.css +0 -0
- package/components/Video/index.d.ts +119 -0
- package/components/Video/index.js +358 -0
- package/components/Video/styles.module.css +0 -0
- package/components/Video/utils.d.ts +10 -0
- package/components/_WIP_AudioQuote/index.d.ts +1 -0
- package/components/_WIP_AudioQuote/index.js +0 -0
- package/components/_WIP_Icon/index.d.ts +1 -0
- package/components/_WIP_Icon/index.js +0 -0
- package/components/index.d.ts +15 -1
- package/components/index.js +15 -1
- package/components/public-classnames.d.ts +14 -3
- package/components/utils/index.d.ts +1 -0
- package/components/utils/index.js +12 -0
- package/components/utils/types.d.ts +3 -0
- package/components/utils/types.js +0 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/node/@aws-s3/index.test.d.ts +1 -0
- package/node/@aws-s3/storage/directory/index.d.ts +1 -1
- package/node/@aws-s3/storage/directory/index.js +1 -1
- package/node/@aws-s3/storage/file/index.d.ts +3 -3
- package/node/@aws-s3/storage/file/index.js +3 -3
- package/node/@google-cloud/storage/directory/index.d.ts +2 -2
- package/node/@google-cloud/storage/directory/index.js +2 -2
- package/node/@google-cloud/storage/file/index.d.ts +4 -4
- package/node/@google-cloud/storage/file/index.js +4 -4
- package/node/cloud-storage/operations/index.d.ts +3 -3
- package/node/cloud-storage/operations/index.js +3 -3
- package/node/encryption/index.d.ts +1 -1
- package/node/encryption/index.js +1 -1
- package/node/files/index.d.ts +1 -1
- package/node/files/index.js +1 -1
- package/node/ftps/directory/index.d.ts +2 -2
- package/node/ftps/directory/index.js +2 -2
- package/node/ftps/file/index.d.ts +1 -1
- package/node/ftps/file/index.js +1 -1
- package/node/images/index.d.ts +3 -3
- package/node/images/index.js +3 -3
- package/node/images/transform/operations/index.d.ts +6 -6
- package/node/images/transform/operations/index.js +6 -6
- package/node/index.d.ts +4 -4
- package/node/index.js +4 -4
- package/node/process/spawner/index.d.ts +61 -2
- package/node/process/spawner/index.js +6 -6
- package/node/sftp/file/index.d.ts +3 -3
- package/node/sftp/file/index.js +3 -3
- package/package.json +1030 -13
- package/components/Input/index.d.ts +0 -7
- package/components/Input/index.js +0 -29
- /package/components/{Input → Disclaimer}/styles.module.css +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type FunctionComponent, type PropsWithChildren, type VideoHTMLAttributes } from 'react';
|
|
2
|
+
import { type Props as DisclaimerProps } from '../Disclaimer/index.js';
|
|
3
|
+
import { type Props as SubsProps } from '../Subtitles/index.js';
|
|
4
|
+
import type { WithClassName } from '../utils/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Describes a single video source.
|
|
7
|
+
*
|
|
8
|
+
* @property src - URL of the video file.
|
|
9
|
+
* @property type - MIME type of the source (e.g. `'video/mp4'`).
|
|
10
|
+
*/
|
|
11
|
+
type SourceData = {
|
|
12
|
+
src?: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Describes a single text track (subtitles, captions, chapters, etc.).
|
|
17
|
+
*
|
|
18
|
+
* @property src - URL of the track file.
|
|
19
|
+
* @property kind - Track type, maps directly to the `<track>` `kind` attribute.
|
|
20
|
+
* @property srclang - Language of the track content (e.g. `'fr'`, `'en'`).
|
|
21
|
+
* @property label - Human-readable label shown in the browser's track selector.
|
|
22
|
+
* @property default - When `true`, marks this track as the default selection.
|
|
23
|
+
*/
|
|
24
|
+
type TrackData = {
|
|
25
|
+
src?: string;
|
|
26
|
+
kind?: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
|
|
27
|
+
srclang?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
default?: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Props for the {@link Video} component.
|
|
33
|
+
*
|
|
34
|
+
* Extends all native `VideoHTMLAttributes<HTMLVideoElement>`, so any standard
|
|
35
|
+
* video attribute (`autoPlay`, `muted`, `loop`, `poster`, etc.) can be passed
|
|
36
|
+
* and will be forwarded to the underlying `<video>` element.
|
|
37
|
+
*
|
|
38
|
+
* @property sources - One or more video sources. Accepts:
|
|
39
|
+
* - a single URL string,
|
|
40
|
+
* - an array of URL strings,
|
|
41
|
+
* - an array of {@link SourceData} objects for fine-grained `type` control.
|
|
42
|
+
* @property tracks - One or more text tracks. Accepts:
|
|
43
|
+
* - a single URL string,
|
|
44
|
+
* - an array of URL strings,
|
|
45
|
+
* - an array of {@link TrackData} objects.
|
|
46
|
+
* @property playBtnContent - Custom content for the play button.
|
|
47
|
+
* @property pauseBtnContent - Custom content for the pause button.
|
|
48
|
+
* @property loudBtnContent - Custom content for the unmute button.
|
|
49
|
+
* @property muteBtnContent - Custom content for the mute button.
|
|
50
|
+
* @property fullScreenBtnContent - Custom content for the fullScreen button.
|
|
51
|
+
* @property subtitles - Props forwarded to the internal {@link Subtitles} component.
|
|
52
|
+
* `timecodeMs` is injected automatically from the current playback position.
|
|
53
|
+
* @property disclaimer - Props forwarded to the internal {@link Disclaimer} component.
|
|
54
|
+
* While the disclaimer is active, `autoPlay` and `muted` are suppressed on the
|
|
55
|
+
* underlying `<video>` element.
|
|
56
|
+
* @property autoPlayWhenVisible - When `true`, triggers playback the first time the
|
|
57
|
+
* component intersects the viewport, provided no disclaimer is active.
|
|
58
|
+
* @property autoPauseWhenHidden - When `true`, pauses playback whenever the component
|
|
59
|
+
* leaves the viewport.
|
|
60
|
+
* @property autoLoudWhenVisible - When `true`, unmutes the video the first time the
|
|
61
|
+
* component intersects the viewport, provided no disclaimer is active.
|
|
62
|
+
* @property autoMuteWhenHidden - When `true`, mutes the video whenever the component
|
|
63
|
+
* leaves the viewport.
|
|
64
|
+
* @property className - Optional additional class name(s) applied to the root element.
|
|
65
|
+
* @property children - React children rendered inside the `<video>` element itself
|
|
66
|
+
* (e.g. fallback content).
|
|
67
|
+
*/
|
|
68
|
+
export type Props = PropsWithChildren<WithClassName<{
|
|
69
|
+
sources?: string | string[] | SourceData[];
|
|
70
|
+
tracks?: string | string[] | TrackData[];
|
|
71
|
+
playBtnContent?: React.ReactNode;
|
|
72
|
+
pauseBtnContent?: React.ReactNode;
|
|
73
|
+
loudBtnContent?: React.ReactNode;
|
|
74
|
+
muteBtnContent?: React.ReactNode;
|
|
75
|
+
fullScreenBtnContent?: React.ReactNode;
|
|
76
|
+
subtitles?: SubsProps;
|
|
77
|
+
disclaimer?: DisclaimerProps;
|
|
78
|
+
autoPlayWhenVisible?: boolean;
|
|
79
|
+
autoPauseWhenHidden?: boolean;
|
|
80
|
+
autoLoudWhenVisible?: boolean;
|
|
81
|
+
autoMuteWhenHidden?: boolean;
|
|
82
|
+
}> & VideoHTMLAttributes<HTMLVideoElement>>;
|
|
83
|
+
/**
|
|
84
|
+
* Full-featured video player component. Wraps a native `<video>` element with
|
|
85
|
+
* playback controls, volume, playback rate, a timeline, optional subtitles,
|
|
86
|
+
* an optional disclaimer gate, and viewport-driven auto-play/mute behaviours.
|
|
87
|
+
*
|
|
88
|
+
* ### Root element modifiers
|
|
89
|
+
* The root `<figure>` receives the public class name defined by `video` and
|
|
90
|
+
* the following BEM-style modifier classes:
|
|
91
|
+
* - `--play-on` / `--play-off` — reflects current playback state.
|
|
92
|
+
* - `--fullscreen-on` / `--fullscreen-off` — reflects fullscreen state.
|
|
93
|
+
* - `--loud` / `--muted` — reflects mute state.
|
|
94
|
+
*
|
|
95
|
+
* ### Data attributes on the root element
|
|
96
|
+
* - `data-play-on` — present (empty string) when playing.
|
|
97
|
+
* - `data-play-off` — present (empty string) when paused.
|
|
98
|
+
* - `data-fullscreen-on` — present (empty string) when in fullScreen.
|
|
99
|
+
* - `data-fullscreen-off` — present (empty string) when not in fullScreen.
|
|
100
|
+
* - `data-loud` — present (empty string) when unmuted.
|
|
101
|
+
* - `data-muted` — present (empty string) when muted.
|
|
102
|
+
* - `data-volume` — current volume as a `0–1` float.
|
|
103
|
+
* - `data-volume-percent` — current volume as a `0–100` float.
|
|
104
|
+
* - `data-playback-rate` — current playback rate (e.g. `1`, `1.5`).
|
|
105
|
+
* - `data-current-time-ms` — current time in milliseconds, fixed to 2 decimals.
|
|
106
|
+
* - `data-current-time-ratio` — current / total ratio, fixed to 8 decimals.
|
|
107
|
+
* - `data-total-time-ms` — total duration in milliseconds.
|
|
108
|
+
*
|
|
109
|
+
* ### CSS custom properties on the root element
|
|
110
|
+
* - `--video-current-time-ratio` — current / total ratio, fixed to 8 decimals.
|
|
111
|
+
* Useful for driving progress-bar animations purely in CSS.
|
|
112
|
+
*
|
|
113
|
+
* @param props - Component properties.
|
|
114
|
+
* @see {@link Props}
|
|
115
|
+
* @returns A `<figure>` element containing the video, its controls, optional
|
|
116
|
+
* subtitles, and an optional disclaimer overlay.
|
|
117
|
+
*/
|
|
118
|
+
export declare const Video: FunctionComponent<Props>;
|
|
119
|
+
export {};
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// src/components/Video/index.tsx
|
|
2
|
+
import {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState
|
|
8
|
+
} from "react";
|
|
9
|
+
import { clss } from "../../agnostic/css/clss/index.js";
|
|
10
|
+
import {
|
|
11
|
+
Disclaimer
|
|
12
|
+
} from "../Disclaimer/index.js";
|
|
13
|
+
import { IntersectionObserverComponent } from "../IntersectionObserver/index.js";
|
|
14
|
+
import {
|
|
15
|
+
Subtitles
|
|
16
|
+
} from "../Subtitles/index.js";
|
|
17
|
+
import { mergeClassNames } from "../utils/index.js";
|
|
18
|
+
import { video as publicClassName } from "../public-classnames.js";
|
|
19
|
+
import {
|
|
20
|
+
formatTime,
|
|
21
|
+
secondsToMs,
|
|
22
|
+
muteAttributeWorkaround,
|
|
23
|
+
forcePlay,
|
|
24
|
+
forcePause,
|
|
25
|
+
forceLoud,
|
|
26
|
+
forceMute,
|
|
27
|
+
forceFullScreen,
|
|
28
|
+
forceExitFullScreen
|
|
29
|
+
} from "./utils.js";
|
|
30
|
+
import cssModule from "./styles.module.css";
|
|
31
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
32
|
+
var Video = ({
|
|
33
|
+
sources,
|
|
34
|
+
tracks,
|
|
35
|
+
playBtnContent,
|
|
36
|
+
pauseBtnContent,
|
|
37
|
+
loudBtnContent,
|
|
38
|
+
muteBtnContent,
|
|
39
|
+
fullScreenBtnContent,
|
|
40
|
+
subtitles,
|
|
41
|
+
disclaimer,
|
|
42
|
+
autoPlayWhenVisible,
|
|
43
|
+
autoPauseWhenHidden,
|
|
44
|
+
autoLoudWhenVisible,
|
|
45
|
+
autoMuteWhenHidden,
|
|
46
|
+
children,
|
|
47
|
+
className,
|
|
48
|
+
...intrinsicVideoAttributes
|
|
49
|
+
}) => {
|
|
50
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
51
|
+
const [isFullScreen, setIsFullScreen] = useState(false);
|
|
52
|
+
const [isLoud, setIsLoud] = useState(false);
|
|
53
|
+
const [currentTime, setCurrentTime] = useState(0);
|
|
54
|
+
const [totalTime, setTotalTime] = useState(0);
|
|
55
|
+
const [volume, setVolume] = useState(0);
|
|
56
|
+
const [playbackRate, setPlaybackRate] = useState(0);
|
|
57
|
+
const [hasBeenAutoPlayed, setHasBeenAutoPlayed] = useState(false);
|
|
58
|
+
const [isDisclaimerOn, setIsDisclaimerOn] = useState(
|
|
59
|
+
disclaimer?.isOn === true || disclaimer?.defaultIsOn === true || disclaimer !== void 0 && disclaimer.defaultIsOn === void 0
|
|
60
|
+
);
|
|
61
|
+
let shouldDisclaimerBeOn = isDisclaimerOn;
|
|
62
|
+
if (disclaimer?.isOn === true) {
|
|
63
|
+
shouldDisclaimerBeOn = true;
|
|
64
|
+
}
|
|
65
|
+
if (disclaimer?.isOn === false) {
|
|
66
|
+
shouldDisclaimerBeOn = false;
|
|
67
|
+
}
|
|
68
|
+
const currentTimeMs = secondsToMs(currentTime);
|
|
69
|
+
const totalTimeMs = useMemo(() => secondsToMs(totalTime), [totalTime]);
|
|
70
|
+
const volumePercent = useMemo(() => volume * 100, [volume]);
|
|
71
|
+
const videoRef = useRef(null);
|
|
72
|
+
const $root = useRef(null);
|
|
73
|
+
const handleMetadataLoadEvent = useCallback((e) => {
|
|
74
|
+
if (videoRef.current === null) return;
|
|
75
|
+
const video = videoRef.current;
|
|
76
|
+
muteAttributeWorkaround(
|
|
77
|
+
video,
|
|
78
|
+
intrinsicVideoAttributes.muted ?? false,
|
|
79
|
+
setIsLoud
|
|
80
|
+
);
|
|
81
|
+
setTotalTime(video.duration);
|
|
82
|
+
setPlaybackRate(video.playbackRate);
|
|
83
|
+
setVolume(video.volume);
|
|
84
|
+
setIsLoud(!video.muted);
|
|
85
|
+
intrinsicVideoAttributes.onLoadedMetadata?.(e);
|
|
86
|
+
}, []);
|
|
87
|
+
const handleVolumeChangeEvent = useCallback((e) => {
|
|
88
|
+
const { volume: volume2 } = e.currentTarget;
|
|
89
|
+
setVolume(volume2);
|
|
90
|
+
intrinsicVideoAttributes.onVolumeChange?.(e);
|
|
91
|
+
}, []);
|
|
92
|
+
const handlePlayEvent = useCallback((e) => {
|
|
93
|
+
setIsPlaying(true);
|
|
94
|
+
setHasBeenAutoPlayed(true);
|
|
95
|
+
intrinsicVideoAttributes.onPlay?.(e);
|
|
96
|
+
}, []);
|
|
97
|
+
const handlePauseEvent = useCallback((e) => {
|
|
98
|
+
setIsPlaying(false);
|
|
99
|
+
intrinsicVideoAttributes.onPause?.(e);
|
|
100
|
+
}, []);
|
|
101
|
+
const handleRateChangeEvent = useCallback((e) => {
|
|
102
|
+
const rate = e.currentTarget.playbackRate;
|
|
103
|
+
setPlaybackRate(rate);
|
|
104
|
+
intrinsicVideoAttributes.onRateChange?.(e);
|
|
105
|
+
}, []);
|
|
106
|
+
const handleTimeUpdateEvent = useCallback((e) => {
|
|
107
|
+
const currentTime2 = e.currentTarget.currentTime;
|
|
108
|
+
setCurrentTime(currentTime2);
|
|
109
|
+
intrinsicVideoAttributes?.onTimeUpdate?.(e);
|
|
110
|
+
}, [totalTime]);
|
|
111
|
+
const handleVolumeRangeChange = useCallback((e) => {
|
|
112
|
+
const volumePercent2 = Number(e.currentTarget.value);
|
|
113
|
+
const volume2 = volumePercent2 / 100;
|
|
114
|
+
if (videoRef.current === null) return;
|
|
115
|
+
videoRef.current.volume = volume2;
|
|
116
|
+
}, []);
|
|
117
|
+
const handleLoudButtonClick = useCallback(() => {
|
|
118
|
+
forceLoud(videoRef.current, setIsLoud);
|
|
119
|
+
}, [forceLoud]);
|
|
120
|
+
const handleMuteButtonClick = useCallback(() => {
|
|
121
|
+
forceMute(videoRef.current, setIsLoud);
|
|
122
|
+
}, []);
|
|
123
|
+
const handlePlayButtonClick = useCallback(() => {
|
|
124
|
+
void forcePlay(videoRef.current, shouldDisclaimerBeOn, setIsPlaying);
|
|
125
|
+
}, [forcePlay, shouldDisclaimerBeOn]);
|
|
126
|
+
const handlePauseButtonClick = useCallback(() => {
|
|
127
|
+
forcePause(videoRef.current, setIsPlaying);
|
|
128
|
+
}, []);
|
|
129
|
+
const handleFullScreenButtonClick = useCallback(() => {
|
|
130
|
+
if (isFullScreen) void forceExitFullScreen(videoRef.current, setIsFullScreen);
|
|
131
|
+
else void forceFullScreen(videoRef.current, shouldDisclaimerBeOn, setIsFullScreen);
|
|
132
|
+
}, [isFullScreen, shouldDisclaimerBeOn]);
|
|
133
|
+
const handleRateRangeChange = useCallback((e) => {
|
|
134
|
+
const rate = Number(e.currentTarget.value);
|
|
135
|
+
if (videoRef.current === null) return;
|
|
136
|
+
videoRef.current.playbackRate = rate;
|
|
137
|
+
}, []);
|
|
138
|
+
const handleTimelineClick = useCallback((e) => {
|
|
139
|
+
if (videoRef.current === null) return;
|
|
140
|
+
const timelineRect = e.currentTarget.getBoundingClientRect();
|
|
141
|
+
const position = e.clientX - timelineRect.left;
|
|
142
|
+
const progress = Math.min(1, Math.max(0, position / timelineRect.width));
|
|
143
|
+
videoRef.current.currentTime = progress * totalTime;
|
|
144
|
+
}, []);
|
|
145
|
+
const handleDisclaimerDismiss = useCallback(() => {
|
|
146
|
+
setIsDisclaimerOn(false);
|
|
147
|
+
if (intrinsicVideoAttributes.autoPlay === true && !hasBeenAutoPlayed) void forcePlay(videoRef.current, shouldDisclaimerBeOn, setIsPlaying);
|
|
148
|
+
}, [disclaimer, intrinsicVideoAttributes.autoPlay, shouldDisclaimerBeOn]);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (isDisclaimerOn !== shouldDisclaimerBeOn) setIsDisclaimerOn(shouldDisclaimerBeOn);
|
|
151
|
+
if (shouldDisclaimerBeOn) {
|
|
152
|
+
forceMute(videoRef.current, setIsLoud);
|
|
153
|
+
forcePause(videoRef.current, setIsPlaying);
|
|
154
|
+
void forceExitFullScreen(videoRef.current, setIsFullScreen);
|
|
155
|
+
} else if (intrinsicVideoAttributes.autoPlay === true) {
|
|
156
|
+
if (videoRef.current === null) return;
|
|
157
|
+
if (hasBeenAutoPlayed) return;
|
|
158
|
+
if (videoRef.current.paused) void forcePlay(videoRef.current, shouldDisclaimerBeOn, setIsPlaying);
|
|
159
|
+
}
|
|
160
|
+
}, [
|
|
161
|
+
shouldDisclaimerBeOn,
|
|
162
|
+
intrinsicVideoAttributes,
|
|
163
|
+
hasBeenAutoPlayed
|
|
164
|
+
]);
|
|
165
|
+
const parsedSources = useMemo(() => {
|
|
166
|
+
if (sources === void 0) return [];
|
|
167
|
+
if (typeof sources === "string") return [{ src: sources }];
|
|
168
|
+
if (Array.isArray(sources)) {
|
|
169
|
+
if (sources.length === 0) return [];
|
|
170
|
+
if (typeof sources[0] === "string") return sources.map((src) => ({ src }));
|
|
171
|
+
return sources;
|
|
172
|
+
}
|
|
173
|
+
return [];
|
|
174
|
+
}, [sources]);
|
|
175
|
+
const parsedTracks = useMemo(() => {
|
|
176
|
+
if (tracks === void 0) return [];
|
|
177
|
+
if (typeof tracks === "string") return [{ src: tracks }];
|
|
178
|
+
if (Array.isArray(tracks)) {
|
|
179
|
+
if (tracks.length === 0) return [];
|
|
180
|
+
if (typeof tracks[0] === "string") return tracks.map((src) => ({ src }));
|
|
181
|
+
return tracks;
|
|
182
|
+
}
|
|
183
|
+
return [];
|
|
184
|
+
}, [tracks]);
|
|
185
|
+
const c = clss(publicClassName, { cssModule });
|
|
186
|
+
const rootClss = mergeClassNames(c(null, {
|
|
187
|
+
"play-on": isPlaying,
|
|
188
|
+
"play-off": !isPlaying,
|
|
189
|
+
"fullscreen-on": isFullScreen,
|
|
190
|
+
"fullscreen-off": !isFullScreen,
|
|
191
|
+
"loud": isLoud,
|
|
192
|
+
"muted": !isLoud
|
|
193
|
+
}), className);
|
|
194
|
+
const rootAttributes = {
|
|
195
|
+
"data-play-on": isPlaying ? "" : void 0,
|
|
196
|
+
"data-play-off": !isPlaying ? "" : void 0,
|
|
197
|
+
"data-fullscreen-on": isFullScreen ? "" : void 0,
|
|
198
|
+
"data-fullscreen-off": !isFullScreen ? "" : void 0,
|
|
199
|
+
"data-loud": isLoud ? "" : void 0,
|
|
200
|
+
"data-muted": !isLoud ? "" : void 0,
|
|
201
|
+
"data-volume": volume,
|
|
202
|
+
"data-volume-percent": volumePercent,
|
|
203
|
+
"data-playback-rate": playbackRate,
|
|
204
|
+
"data-current-time-ms": currentTimeMs.toFixed(2),
|
|
205
|
+
"data-current-time-ratio": (currentTime / totalTime).toFixed(8),
|
|
206
|
+
"data-total-time-ms": totalTimeMs
|
|
207
|
+
};
|
|
208
|
+
const rootStyles = {
|
|
209
|
+
[`--${publicClassName}-current-time-ratio`]: (currentTime / totalTime).toFixed(8)
|
|
210
|
+
};
|
|
211
|
+
const videoClss = c("video");
|
|
212
|
+
const videoControlsClss = c("video-controls");
|
|
213
|
+
const playBtnClss = c("play-btn");
|
|
214
|
+
const pauseBtnClss = c("pause-btn");
|
|
215
|
+
const loudBtnClss = c("loud-btn");
|
|
216
|
+
const muteBtnClss = c("mute-btn");
|
|
217
|
+
const volumePcntClss = c("volume-percent");
|
|
218
|
+
const fullScreenBtnClss = c("fullscreen-btn");
|
|
219
|
+
const volumeRangeClss = c("volume-range");
|
|
220
|
+
const playbackRateRangeClss = c("playback-rate-range");
|
|
221
|
+
const playbackRateClss = c("playback-rate");
|
|
222
|
+
const timeControlsClss = c("time-controls");
|
|
223
|
+
const currentTimeClss = c("current-time");
|
|
224
|
+
const totalTimeClss = c("total-time");
|
|
225
|
+
const timelineClss = c("timeline");
|
|
226
|
+
const sensitiveContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
227
|
+
/* @__PURE__ */ jsxs(
|
|
228
|
+
"video",
|
|
229
|
+
{
|
|
230
|
+
ref: videoRef,
|
|
231
|
+
className: videoClss,
|
|
232
|
+
onVolumeChange: handleVolumeChangeEvent,
|
|
233
|
+
onLoadedMetadata: handleMetadataLoadEvent,
|
|
234
|
+
onPlay: handlePlayEvent,
|
|
235
|
+
onPause: handlePauseEvent,
|
|
236
|
+
onTimeUpdate: handleTimeUpdateEvent,
|
|
237
|
+
onRateChange: handleRateChangeEvent,
|
|
238
|
+
...intrinsicVideoAttributes,
|
|
239
|
+
autoPlay: shouldDisclaimerBeOn ? false : intrinsicVideoAttributes.autoPlay,
|
|
240
|
+
muted: shouldDisclaimerBeOn ? true : intrinsicVideoAttributes.muted,
|
|
241
|
+
children: [
|
|
242
|
+
parsedSources.map(
|
|
243
|
+
(source, index) => typeof source === "string" ? /* @__PURE__ */ jsx(
|
|
244
|
+
"source",
|
|
245
|
+
{
|
|
246
|
+
src: source
|
|
247
|
+
},
|
|
248
|
+
index
|
|
249
|
+
) : /* @__PURE__ */ jsx(
|
|
250
|
+
"source",
|
|
251
|
+
{
|
|
252
|
+
src: source.src,
|
|
253
|
+
type: source.type
|
|
254
|
+
},
|
|
255
|
+
index
|
|
256
|
+
)
|
|
257
|
+
),
|
|
258
|
+
parsedTracks.map(
|
|
259
|
+
(track, index) => typeof track === "string" ? /* @__PURE__ */ jsx(
|
|
260
|
+
"track",
|
|
261
|
+
{
|
|
262
|
+
src: track
|
|
263
|
+
},
|
|
264
|
+
index
|
|
265
|
+
) : /* @__PURE__ */ jsx(
|
|
266
|
+
"track",
|
|
267
|
+
{
|
|
268
|
+
src: track.src,
|
|
269
|
+
kind: track.kind,
|
|
270
|
+
srcLang: track.srclang,
|
|
271
|
+
label: track.label,
|
|
272
|
+
default: track.default
|
|
273
|
+
},
|
|
274
|
+
index
|
|
275
|
+
)
|
|
276
|
+
),
|
|
277
|
+
children
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
),
|
|
281
|
+
/* @__PURE__ */ jsxs("div", { className: videoControlsClss, children: [
|
|
282
|
+
/* @__PURE__ */ jsx("button", { className: playBtnClss, onClick: handlePlayButtonClick, children: playBtnContent }),
|
|
283
|
+
/* @__PURE__ */ jsx("button", { className: pauseBtnClss, onClick: handlePauseButtonClick, children: pauseBtnContent }),
|
|
284
|
+
/* @__PURE__ */ jsx("button", { className: loudBtnClss, onClick: handleLoudButtonClick, children: loudBtnContent }),
|
|
285
|
+
/* @__PURE__ */ jsx("button", { className: muteBtnClss, onClick: handleMuteButtonClick, children: muteBtnContent }),
|
|
286
|
+
/* @__PURE__ */ jsx(
|
|
287
|
+
"input",
|
|
288
|
+
{
|
|
289
|
+
type: "range",
|
|
290
|
+
className: volumeRangeClss,
|
|
291
|
+
value: volumePercent,
|
|
292
|
+
onChange: handleVolumeRangeChange,
|
|
293
|
+
min: 0,
|
|
294
|
+
max: 100,
|
|
295
|
+
step: 1
|
|
296
|
+
}
|
|
297
|
+
),
|
|
298
|
+
/* @__PURE__ */ jsx("span", { className: volumePcntClss, children: volumePercent }),
|
|
299
|
+
/* @__PURE__ */ jsx("button", { className: fullScreenBtnClss, onClick: handleFullScreenButtonClick, children: fullScreenBtnContent }),
|
|
300
|
+
/* @__PURE__ */ jsx(
|
|
301
|
+
"input",
|
|
302
|
+
{
|
|
303
|
+
type: "range",
|
|
304
|
+
className: playbackRateRangeClss,
|
|
305
|
+
value: playbackRate,
|
|
306
|
+
onChange: handleRateRangeChange,
|
|
307
|
+
min: 0.25,
|
|
308
|
+
max: 4,
|
|
309
|
+
step: 0.25
|
|
310
|
+
}
|
|
311
|
+
),
|
|
312
|
+
/* @__PURE__ */ jsx("span", { className: playbackRateClss, children: playbackRate })
|
|
313
|
+
] }),
|
|
314
|
+
/* @__PURE__ */ jsxs("div", { className: timeControlsClss, children: [
|
|
315
|
+
/* @__PURE__ */ jsx("span", { className: currentTimeClss, children: formatTime(currentTimeMs, "mm:ss:ms") }),
|
|
316
|
+
/* @__PURE__ */ jsx("span", { className: totalTimeClss, children: formatTime(totalTimeMs, "mm:ss:ms") }),
|
|
317
|
+
/* @__PURE__ */ jsx("div", { className: timelineClss, onClick: handleTimelineClick })
|
|
318
|
+
] }),
|
|
319
|
+
subtitles !== void 0 && /* @__PURE__ */ jsx(
|
|
320
|
+
Subtitles,
|
|
321
|
+
{
|
|
322
|
+
...subtitles,
|
|
323
|
+
timecodeMs: currentTimeMs
|
|
324
|
+
}
|
|
325
|
+
)
|
|
326
|
+
] });
|
|
327
|
+
const disclaimedContent = disclaimer !== void 0 ? /* @__PURE__ */ jsx(
|
|
328
|
+
Disclaimer,
|
|
329
|
+
{
|
|
330
|
+
...disclaimer,
|
|
331
|
+
isOn: shouldDisclaimerBeOn,
|
|
332
|
+
actionHandlers: {
|
|
333
|
+
dismissClick: handleDisclaimerDismiss
|
|
334
|
+
},
|
|
335
|
+
children: sensitiveContent
|
|
336
|
+
}
|
|
337
|
+
) : sensitiveContent;
|
|
338
|
+
const observedContent = autoLoudWhenVisible === true || autoMuteWhenHidden === true || autoPlayWhenVisible === true || autoPauseWhenHidden === true ? /* @__PURE__ */ jsx(IntersectionObserverComponent, { onIntersected: ({ ioEntry }) => {
|
|
339
|
+
const { isIntersecting = false } = ioEntry ?? {};
|
|
340
|
+
if (autoMuteWhenHidden === true && !isIntersecting) forceMute(videoRef.current, setIsLoud);
|
|
341
|
+
if (autoPauseWhenHidden === true && !isIntersecting) forcePause(videoRef.current, setIsPlaying);
|
|
342
|
+
if (autoPlayWhenVisible === true && !hasBeenAutoPlayed && !shouldDisclaimerBeOn && isIntersecting) void forcePlay(videoRef.current, shouldDisclaimerBeOn, setIsPlaying);
|
|
343
|
+
if (autoLoudWhenVisible === true && !hasBeenAutoPlayed && !shouldDisclaimerBeOn && isIntersecting) forceLoud(videoRef.current, setIsLoud);
|
|
344
|
+
}, children: disclaimedContent }) : disclaimedContent;
|
|
345
|
+
return /* @__PURE__ */ jsx(
|
|
346
|
+
"figure",
|
|
347
|
+
{
|
|
348
|
+
className: rootClss,
|
|
349
|
+
...rootAttributes,
|
|
350
|
+
ref: $root,
|
|
351
|
+
style: rootStyles,
|
|
352
|
+
children: observedContent
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
};
|
|
356
|
+
export {
|
|
357
|
+
Video
|
|
358
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Dispatch, SetStateAction } from 'react';
|
|
2
|
+
export declare const muteAttributeWorkaround: (video: HTMLVideoElement | null, shouldMute: boolean, setIsSoundOn: Dispatch<SetStateAction<boolean>>) => void;
|
|
3
|
+
export declare const forceMute: (video: HTMLVideoElement | null, setIsSoundOn: Dispatch<SetStateAction<boolean>>) => void;
|
|
4
|
+
export declare const forceLoud: (video: HTMLVideoElement | null, setIsSoundOn: Dispatch<SetStateAction<boolean>>) => void;
|
|
5
|
+
export declare const forcePlay: (video: HTMLVideoElement | null, shouldDisclaimerBeOn: boolean, setIsPlaying: Dispatch<SetStateAction<boolean>>) => Promise<void>;
|
|
6
|
+
export declare const forcePause: (video: HTMLVideoElement | null, setIsPlaying: Dispatch<SetStateAction<boolean>>) => void;
|
|
7
|
+
export declare const forceFullScreen: (video: HTMLVideoElement | null, shouldDisclaimerBeOn: boolean, setIsFullscreen: Dispatch<SetStateAction<boolean>>) => Promise<void>;
|
|
8
|
+
export declare const forceExitFullScreen: (video: HTMLVideoElement | null, setIsFullscreen: Dispatch<SetStateAction<boolean>>) => Promise<void>;
|
|
9
|
+
export declare function secondsToMs(seconds: number): number;
|
|
10
|
+
export declare function formatTime(ms: number, format: string, fps?: number): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
package/components/index.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export * as disclaimer from './Disclaimer/index.js'
|
|
2
|
+
export * as drawer from './Drawer/index.js'
|
|
1
3
|
export * as eventListener from './EventListener/index.js'
|
|
2
|
-
export * as
|
|
4
|
+
export * as gallery from './Gallery/index.js'
|
|
5
|
+
export * as image from './Image/index.js'
|
|
3
6
|
export * as intersectionObserver from './IntersectionObserver/index.js'
|
|
7
|
+
export * as paginator from './Paginator/index.js'
|
|
8
|
+
export * as resizeObserver from './ResizeObserver/index.js'
|
|
9
|
+
export * as scrllgngn from './Scrllgngn/index.js'
|
|
10
|
+
export * as sequencer from './Sequencer/index.js'
|
|
11
|
+
export * as shadowRoot from './ShadowRoot/index.js'
|
|
12
|
+
export * as subtitles from './Subtitles/index.js'
|
|
13
|
+
export * as theatre from './Theatre/index.js'
|
|
14
|
+
export * as video from './Video/index.js'
|
|
15
|
+
export * as wipAudioQuote from './_WIP_AudioQuote/index.js'
|
|
16
|
+
export * as wipIcon from './_WIP_Icon/index.js'
|
|
17
|
+
export * as utils from './utils/index.js'
|
package/components/index.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export * as disclaimer from './Disclaimer/index.js'
|
|
2
|
+
export * as drawer from './Drawer/index.js'
|
|
1
3
|
export * as eventListener from './EventListener/index.js'
|
|
2
|
-
export * as
|
|
4
|
+
export * as gallery from './Gallery/index.js'
|
|
5
|
+
export * as image from './Image/index.js'
|
|
3
6
|
export * as intersectionObserver from './IntersectionObserver/index.js'
|
|
7
|
+
export * as paginator from './Paginator/index.js'
|
|
8
|
+
export * as resizeObserver from './ResizeObserver/index.js'
|
|
9
|
+
export * as scrllgngn from './Scrllgngn/index.js'
|
|
10
|
+
export * as sequencer from './Sequencer/index.js'
|
|
11
|
+
export * as shadowRoot from './ShadowRoot/index.js'
|
|
12
|
+
export * as subtitles from './Subtitles/index.js'
|
|
13
|
+
export * as theatre from './Theatre/index.js'
|
|
14
|
+
export * as video from './Video/index.js'
|
|
15
|
+
export * as wipAudioQuote from './_WIP_AudioQuote/index.js'
|
|
16
|
+
export * as wipIcon from './_WIP_Icon/index.js'
|
|
17
|
+
export * as utils from './utils/index.js'
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
1
|
+
export declare const disclaimer = "dsed-disclaimer";
|
|
2
|
+
export declare const drawer = "dsed-drawer";
|
|
3
|
+
export declare const eventListener = "dsed-event-listener";
|
|
4
|
+
export declare const gallery = "dsed-gallery";
|
|
5
|
+
export declare const image = "dsed-image";
|
|
6
|
+
export declare const intersectionObserver = "dsed-intersection-observer";
|
|
7
|
+
export declare const paginator = "dsed-paginator";
|
|
8
|
+
export declare const resizeObserver = "dsed-resize-observer";
|
|
9
|
+
export declare const scrllgngn = "dsed-scrllgngn";
|
|
10
|
+
export declare const sequencer = "dsed-sequencer";
|
|
11
|
+
export declare const shadowRoot = "dsed-shadow-root";
|
|
12
|
+
export declare const subtitles = "dsed-subtitles";
|
|
13
|
+
export declare const theatre = "dsed-theatre";
|
|
14
|
+
export declare const video = "dsed-video";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function mergeClassNames(...names: Array<string | null | undefined | Array<string | null | undefined>>): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/components/utils/index.tsx
|
|
2
|
+
function mergeClassNames(...names) {
|
|
3
|
+
return names.map((name) => {
|
|
4
|
+
if (typeof name !== "string" && !Array.isArray(name)) return false;
|
|
5
|
+
if (Array.isArray(name)) return mergeClassNames(...name);
|
|
6
|
+
if (name.trim() === "") return false;
|
|
7
|
+
return name.trim();
|
|
8
|
+
}).filter((name) => typeof name === "string").join(" ");
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
mergeClassNames
|
|
12
|
+
};
|
|
File without changes
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * as copy from './copy/index.js'
|
|
2
1
|
export * as download from './download/index.js'
|
|
3
2
|
export * as exists from './exists/index.js'
|
|
4
|
-
export * as remove from './remove/index.js'
|
|
5
3
|
export * as move from './move/index.js'
|
|
6
|
-
export * as
|
|
4
|
+
export * as remove from './remove/index.js'
|
|
7
5
|
export * as stat from './stat/index.js'
|
|
6
|
+
export * as upload from './upload/index.js'
|
|
7
|
+
export * as copy from './copy/index.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * as copy from './copy/index.js'
|
|
2
1
|
export * as download from './download/index.js'
|
|
3
2
|
export * as exists from './exists/index.js'
|
|
4
|
-
export * as remove from './remove/index.js'
|
|
5
3
|
export * as move from './move/index.js'
|
|
6
|
-
export * as
|
|
4
|
+
export * as remove from './remove/index.js'
|
|
7
5
|
export * as stat from './stat/index.js'
|
|
6
|
+
export * as upload from './upload/index.js'
|
|
7
|
+
export * as copy from './copy/index.js'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * as list from './list/index.js'
|
|
2
1
|
export * as copyDir from './copy-dir/index.js'
|
|
3
|
-
export * as
|
|
2
|
+
export * as list from './list/index.js'
|
|
4
3
|
export * as removeDir from './remove-dir/index.js'
|
|
4
|
+
export * as moveDir from './move-dir/index.js'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * as list from './list/index.js'
|
|
2
1
|
export * as copyDir from './copy-dir/index.js'
|
|
3
|
-
export * as
|
|
2
|
+
export * as list from './list/index.js'
|
|
4
3
|
export * as removeDir from './remove-dir/index.js'
|
|
4
|
+
export * as moveDir from './move-dir/index.js'
|