@sgrsoft/vpe-react-ui 0.2.12 → 0.2.13
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/README.md +259 -196
- package/package.json +1 -1
- package/dist/vpe-react-ui.css +0 -1
- package/dist/vpe-react-ui.es.js +0 -312
- package/dist/vpe-react-ui.umd.js +0 -1
package/README.md
CHANGED
|
@@ -1,244 +1,307 @@
|
|
|
1
|
-
#
|
|
1
|
+
# vpe-react-ui
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
React 기반 비디오 플레이어 UI 컴포넌트 모음입니다. 스트리밍 엔진(HLS/DASH)은 외부에서 주입하고, UI는 이 패키지에서 제공합니다. 여러 플레이어를 동시에 렌더링할 수 있도록 스토어 스코프를 지원합니다.
|
|
4
|
+
|
|
5
|
+
## 주요 특징
|
|
6
|
+
|
|
7
|
+
- HLS/DASH/MP4/Native(HLS) 재생 UI 제공
|
|
8
|
+
- hls.js, dash.js는 선택적 주입(옵셔널 peer dependency)
|
|
9
|
+
- 자막 트랙(VTT) 지원 및 자막 선택/토글 UI 제공
|
|
10
|
+
- 품질 선택, 재생 속도, PiP, 전체화면, 음량, 공유 등 UI 컴포넌트 제공
|
|
11
|
+
- 모바일 더블탭 탐색 오버레이, 워터마크, 시작 시간 표시 등 부가 UI 제공
|
|
12
|
+
- `PlayerStoreProvider`로 플레이어별 상태 스코프 분리 가능
|
|
4
13
|
|
|
5
14
|
## 설치
|
|
15
|
+
|
|
6
16
|
```bash
|
|
7
17
|
pnpm add @sgrsoft/vpe-react-ui
|
|
8
|
-
# 선택: 스트리밍 라이브러리
|
|
9
|
-
pnpm add hls.js dashjs
|
|
10
18
|
```
|
|
11
|
-
- hls.js/dashjs는 선택적 peerDependency입니다. 브라우저/CDN 또는 `import Hls from "hls.js"`, `import dashjs from "dashjs"`로 주입하세요.
|
|
12
19
|
|
|
20
|
+
필수 peer dependency:
|
|
21
|
+
|
|
22
|
+
- `react`
|
|
23
|
+
- `react-dom`
|
|
24
|
+
|
|
25
|
+
선택적 주입:
|
|
26
|
+
|
|
27
|
+
- `hls.js`
|
|
28
|
+
- `dashjs`
|
|
29
|
+
|
|
30
|
+
## 기본 사용 예시
|
|
13
31
|
|
|
14
|
-
## 사용법
|
|
15
|
-
### React (ESM)
|
|
16
32
|
```tsx
|
|
33
|
+
import {
|
|
34
|
+
BaseStyle,
|
|
35
|
+
PlayerStoreProvider,
|
|
36
|
+
HlsVideo,
|
|
37
|
+
SeekBar,
|
|
38
|
+
PlayBtn,
|
|
39
|
+
CurrentTimeBtn,
|
|
40
|
+
DurationBtn,
|
|
41
|
+
VolumeBtn,
|
|
42
|
+
FullscreenBtn,
|
|
43
|
+
SettingBtn,
|
|
44
|
+
SettingModal,
|
|
45
|
+
} from "@sgrsoft/vpe-react-ui";
|
|
46
|
+
|
|
17
47
|
import Hls from "hls.js";
|
|
18
|
-
import dashjs from "dashjs";
|
|
19
|
-
import { VpePlayer } from "@sgrsoft/vpe-react-ui";
|
|
20
48
|
|
|
21
|
-
export function
|
|
49
|
+
export default function Player() {
|
|
50
|
+
const src = {
|
|
51
|
+
file: "https://example.com/stream.m3u8",
|
|
52
|
+
poster: "https://example.com/poster.jpg",
|
|
53
|
+
vtt: [
|
|
54
|
+
{ label: "KOR", id: "ko", default: true, src: "https://example.com/ko.vtt" },
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const options = {
|
|
59
|
+
autostart: false,
|
|
60
|
+
autoPause: true,
|
|
61
|
+
objectFit: "contain",
|
|
62
|
+
playbackRate: 1,
|
|
63
|
+
lowLatencyMode: false,
|
|
64
|
+
};
|
|
65
|
+
|
|
22
66
|
return (
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
<PlayerStoreProvider>
|
|
68
|
+
<BaseStyle />
|
|
69
|
+
<div className="vpe-root-wrap">
|
|
70
|
+
<HlsVideo src={src} hlsLib={Hls} options={options} />
|
|
71
|
+
|
|
72
|
+
<div className="controls">
|
|
73
|
+
<SeekBar src={src} hlsLib={Hls} />
|
|
74
|
+
<PlayBtn />
|
|
75
|
+
<CurrentTimeBtn />
|
|
76
|
+
<DurationBtn />
|
|
77
|
+
<VolumeBtn />
|
|
78
|
+
<FullscreenBtn />
|
|
79
|
+
<SettingBtn />
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<SettingModal
|
|
83
|
+
text={{
|
|
84
|
+
setting: "설정",
|
|
85
|
+
quality: "화질",
|
|
86
|
+
autoplay: "자동 재생",
|
|
87
|
+
playbackRate: "재생 속도",
|
|
88
|
+
captions: "자막",
|
|
89
|
+
auto: "자동",
|
|
90
|
+
notUse: "사용 안 함",
|
|
91
|
+
}}
|
|
92
|
+
src={src}
|
|
93
|
+
options={{ playRateSetting: [0.5, 1, 1.5, 2] }}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</PlayerStoreProvider>
|
|
35
97
|
);
|
|
36
98
|
}
|
|
37
99
|
```
|
|
38
100
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
101
|
+
## 공통 레이아웃 규칙
|
|
102
|
+
|
|
103
|
+
- 루트 컨테이너에 `vpe-root-wrap` 클래스를 권장합니다.
|
|
104
|
+
- 전체화면 대상 엘리먼트를 지정하려면 `vpe-fullscreen-target` 클래스를 사용합니다.
|
|
105
|
+
- `BaseStyle` 컴포넌트는 필수는 아니지만 기본 스타일(폰트, 버튼, 모달, 오버레이 등)을 제공합니다.
|
|
106
|
+
|
|
107
|
+
## 비디오 컴포넌트
|
|
108
|
+
|
|
109
|
+
### `HlsVideo`
|
|
110
|
+
|
|
111
|
+
- hls.js가 주입되면 MSE 기반 HLS 재생을 사용합니다.
|
|
112
|
+
- hls.js 미지원 환경에서는 네이티브 HLS로 폴백합니다.
|
|
113
|
+
- `options.retry`로 재시도 횟수/간격을 설정할 수 있습니다.
|
|
114
|
+
- `options.lowLatencyMode` 사용 시 저지연 모드 설정을 시도합니다.
|
|
115
|
+
|
|
116
|
+
### `DashVideo`
|
|
117
|
+
|
|
118
|
+
- dash.js가 주입되면 DASH 재생을 사용합니다.
|
|
119
|
+
- dash.js 미주입 시 네이티브 재생으로 폴백합니다.
|
|
120
|
+
|
|
121
|
+
### `Mp4Video`
|
|
122
|
+
|
|
123
|
+
- 일반 MP4 재생용 컴포넌트입니다.
|
|
124
|
+
|
|
125
|
+
### `NativeVideo`
|
|
126
|
+
|
|
127
|
+
- 네이티브 HLS 재생 전용 컴포넌트입니다.
|
|
128
|
+
- FairPlay DRM 지원을 위한 `src.drm` 설정을 제공합니다.
|
|
129
|
+
|
|
130
|
+
#### 비디오 컴포넌트 공통 Props
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
src?: {
|
|
134
|
+
file?: string;
|
|
135
|
+
poster?: string;
|
|
136
|
+
vtt?: Array<{
|
|
137
|
+
label?: string;
|
|
138
|
+
id?: string;
|
|
139
|
+
default?: boolean;
|
|
140
|
+
src?: string;
|
|
141
|
+
}>;
|
|
142
|
+
drm?: Record<string, {
|
|
143
|
+
licenseUri?: string;
|
|
144
|
+
licenseRequestHeader?: Record<string, string | number>;
|
|
145
|
+
certificateUri?: string;
|
|
146
|
+
certificateRequestHeader?: Record<string, string | number>;
|
|
147
|
+
}>;
|
|
148
|
+
};
|
|
149
|
+
options?: {
|
|
150
|
+
autostart?: boolean;
|
|
151
|
+
autoPause?: boolean;
|
|
152
|
+
muted?: boolean;
|
|
153
|
+
objectFit?: string;
|
|
154
|
+
playbackRate?: number;
|
|
155
|
+
lowLatencyMode?: boolean;
|
|
156
|
+
retry?: { maxRetry?: number; interval?: number };
|
|
157
|
+
fairplayContentId?: string;
|
|
158
|
+
};
|
|
159
|
+
onError?: (err: unknown) => void;
|
|
160
|
+
emitEvent?: (type: string, data?: Record<string, unknown>) => void;
|
|
54
161
|
```
|
|
55
162
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
- `.vpe-root-wrap`: 키보드/전체화면 처리에서 기준으로 사용하는 루트 클래스입니다. 플레이어 컨테이너에 적용을 권장합니다.
|
|
82
|
-
|
|
83
|
-
### 비디오 컴포넌트
|
|
84
|
-
모든 비디오 컴포넌트는 공통적으로 다음 props를 받습니다.
|
|
85
|
-
- `src`: `{ file, poster, vtt }` 형태의 소스. `vtt`는 자막 목록 배열입니다.
|
|
86
|
-
- `options`: 내부 동작 옵션. 공통적으로 `autoPause`, `playbackRate`를 지원합니다.
|
|
87
|
-
- `onError`: 에러 콜백.
|
|
88
|
-
- `emitEvent`: `useVideoStateEvents` 이벤트 훅(예: `"timeupdate"`, `"ended"` 등)을 외부로 전달합니다.
|
|
89
|
-
|
|
90
|
-
#### `HlsVideo`
|
|
91
|
-
- HLS(m3u8) 재생 컴포넌트입니다. `hlsLib`에 `hls.js` 인스턴스를 주입합니다.
|
|
92
|
-
- 추가 `options`: `lowLatencyMode`, `retry: { maxRetry, interval }`.
|
|
93
|
-
```tsx
|
|
94
|
-
import Hls from "hls.js";
|
|
95
|
-
import { HlsVideo } from "@sgrsoft/vpe-react-ui";
|
|
96
|
-
|
|
97
|
-
<HlsVideo
|
|
98
|
-
hlsLib={Hls}
|
|
99
|
-
src={{ file: "https://example.com/stream.m3u8", poster: "/poster.jpg" }}
|
|
100
|
-
options={{ lowLatencyMode: true, retry: { maxRetry: 3, interval: 3000 } }}
|
|
101
|
-
/>;
|
|
163
|
+
주의:
|
|
164
|
+
|
|
165
|
+
- `src.vtt`가 제공되면 해당 자막을 우선 사용합니다.
|
|
166
|
+
- `emitEvent`는 `timeupdate`, `ended`, `seeking`, `seeked`, `volumechange` 등 이벤트를 전달합니다.
|
|
167
|
+
- `NativeVideo`의 FairPlay DRM은 Safari 환경을 기준으로 구성되어 있습니다.
|
|
168
|
+
|
|
169
|
+
## UI 컨트롤 컴포넌트
|
|
170
|
+
|
|
171
|
+
### 공통 Props (`PlayBtnProps`)
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
size?: string;
|
|
175
|
+
weight?: "fill";
|
|
176
|
+
color?: string;
|
|
177
|
+
text?: any;
|
|
178
|
+
pos?: "left" | "right";
|
|
179
|
+
options?: any;
|
|
180
|
+
next?: () => void;
|
|
181
|
+
prev?: () => void;
|
|
182
|
+
pidx?: number;
|
|
183
|
+
playlistCnt?: number;
|
|
184
|
+
isMobile?: boolean;
|
|
185
|
+
isPortrait?: boolean;
|
|
186
|
+
isAnimationComplete?: boolean;
|
|
102
187
|
```
|
|
103
188
|
|
|
104
|
-
|
|
105
|
-
- MPEG-DASH(mpd) 재생 컴포넌트입니다. `dashLib`에 `dashjs` 인스턴스를 주입합니다.
|
|
106
|
-
- 추가 `options`: `autostart`, `retry: { maxRetry, interval }`.
|
|
107
|
-
```tsx
|
|
108
|
-
import dashjs from "dashjs";
|
|
109
|
-
import { DashVideo } from "@sgrsoft/vpe-react-ui";
|
|
110
|
-
|
|
111
|
-
<DashVideo
|
|
112
|
-
dashLib={dashjs}
|
|
113
|
-
src={{ file: "https://example.com/stream.mpd" }}
|
|
114
|
-
options={{ autostart: true }}
|
|
115
|
-
/>;
|
|
116
|
-
```
|
|
189
|
+
### 재생 관련
|
|
117
190
|
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
|
|
191
|
+
- `PlayBtn`: 재생/일시정지 토글 버튼
|
|
192
|
+
- `BigPlayBtn`: 중앙 대형 재생 버튼, 모바일에서 이전/다음과 함께 사용 가능
|
|
193
|
+
- `SkipBackBtn`: 기본 10초 뒤로, `options.skipSeconds`로 변경 가능
|
|
194
|
+
- `SkipForwardBtn`: 기본 10초 앞으로, `options.skipSeconds`로 변경 가능
|
|
122
195
|
|
|
123
|
-
|
|
124
|
-
```
|
|
196
|
+
### 시간 표시
|
|
125
197
|
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
```tsx
|
|
130
|
-
import { NativeVideo } from "@sgrsoft/vpe-react-ui";
|
|
198
|
+
- `TimeBtn`: 라이브 시 LIVE 버튼(라이브 엣지로 이동), VOD는 현재/전체 시간 표시
|
|
199
|
+
- `CurrentTimeBtn`: 현재 시간 표시
|
|
200
|
+
- `DurationBtn`: 전체 시간 표시
|
|
131
201
|
|
|
132
|
-
|
|
133
|
-
src={{
|
|
134
|
-
file: "https://example.com/stream.m3u8",
|
|
135
|
-
drm: {
|
|
136
|
-
"com.apple.fps": {
|
|
137
|
-
licenseUri: "https://license.example.com",
|
|
138
|
-
licenseRequestHeader: { Authorization: "Bearer token" },
|
|
139
|
-
certificateUri: "https://license.example.com/cert",
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
}}
|
|
143
|
-
/>;
|
|
144
|
-
```
|
|
202
|
+
### 음량/자막/화면
|
|
145
203
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
204
|
+
- `VolumeBtn`: 음소거 토글 + 볼륨 슬라이더
|
|
205
|
+
- `MuteBtn`: 음소거 토글 버튼만 제공
|
|
206
|
+
- `MuteIcon`: 음소거 상태 표시용 아이콘
|
|
207
|
+
- `SubtitleBtn`: 자막 토글
|
|
208
|
+
- `FullscreenBtn`: 전체화면 토글
|
|
209
|
+
- `PipBtn`: 브라우저 PiP 또는 `options.override.pip`로 커스텀 PiP
|
|
210
|
+
|
|
211
|
+
### 재생목록/네비게이션
|
|
212
|
+
|
|
213
|
+
- `PrevBtn`: 이전 콘텐츠로 이동
|
|
214
|
+
- `NextBtn`: 다음 콘텐츠로 이동
|
|
215
|
+
- `NextPrevBtn`: 이전/다음 버튼 묶음
|
|
158
216
|
|
|
159
|
-
|
|
217
|
+
### 부가 버튼
|
|
218
|
+
|
|
219
|
+
- `SettingBtn`: 설정 모달 열기
|
|
220
|
+
- `ShareBtn`: Web Share API 또는 클립보드 복사
|
|
221
|
+
|
|
222
|
+
## 설정 모달
|
|
223
|
+
|
|
224
|
+
### `SettingModal`
|
|
225
|
+
|
|
226
|
+
- 화질, 재생 속도, 자막 선택 UI 제공
|
|
227
|
+
- `usePlayerController`의 `selectQualityLevel`, `playBackRate`를 내부적으로 사용
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
text: {
|
|
231
|
+
setting: string;
|
|
232
|
+
quality: string;
|
|
233
|
+
autoplay: string;
|
|
234
|
+
playbackRate: string;
|
|
235
|
+
captions: string;
|
|
236
|
+
auto?: string;
|
|
237
|
+
notUse?: string;
|
|
238
|
+
};
|
|
239
|
+
vtt?: SubtitleTrack[];
|
|
240
|
+
src?: { vtt?: SubtitleTrack[] };
|
|
241
|
+
options?: { playRateSetting?: number[]; autostart?: boolean };
|
|
160
242
|
```
|
|
161
243
|
|
|
162
|
-
|
|
163
|
-
아래 버튼들은 공통적으로 `PlayBtnProps`를 사용합니다.
|
|
164
|
-
- 공통 props: `size`, `color`, `weight`, `pos`(팝오버 위치), `text`(라벨 문구), `options`.
|
|
244
|
+
## 오버레이/레이아웃 컴포넌트
|
|
165
245
|
|
|
166
|
-
|
|
167
|
-
-
|
|
246
|
+
- `InitPlayerUi`: 초기 플레이 버튼 오버레이
|
|
247
|
+
- `LoadingUi`: 로딩 스피너 오버레이
|
|
248
|
+
- `StartTimeUi`: 예약/시작 시간 카드 표시
|
|
249
|
+
- `WatermarkUi`: 워터마크 텍스트 표시(랜덤/고정 위치 지원)
|
|
250
|
+
- `DoubleTapSeekOverlay`: 모바일 더블탭 탐색 오버레이
|
|
251
|
+
- `MetaDesc`: 제목/프로필/작성시간 메타 정보 표시
|
|
252
|
+
- `Blank`: 레이아웃용 스페이서
|
|
253
|
+
- `Group`: 버튼 그룹 래퍼
|
|
168
254
|
|
|
169
|
-
|
|
170
|
-
- 중앙 재생 버튼입니다. 모바일/세로 화면에서만 클릭 동작을 수행합니다.
|
|
171
|
-
- 재생목록 컨트롤: `pidx`, `playlistCnt`, `next`, `prev`, `isMobile`, `isPortrait`.
|
|
255
|
+
### `DoubleTapSeekOverlay` Props
|
|
172
256
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
257
|
+
```ts
|
|
258
|
+
seekSeconds?: number;
|
|
259
|
+
doubleTapWindowMs?: number;
|
|
260
|
+
executeDelayMs?: number;
|
|
261
|
+
onSingleTap?: (side: "left" | "right") => void;
|
|
262
|
+
```
|
|
176
263
|
|
|
177
|
-
|
|
178
|
-
- 재생목록 이동 버튼입니다. `pidx`, `playlistCnt`, `prev`, `next` 필요.
|
|
264
|
+
## 훅/상태 관리
|
|
179
265
|
|
|
180
|
-
|
|
181
|
-
- 현재 시간/전체 길이를 표시합니다.
|
|
266
|
+
### `PlayerStoreProvider`
|
|
182
267
|
|
|
183
|
-
|
|
184
|
-
-
|
|
268
|
+
- 동일 페이지에서 여러 플레이어를 분리 관리하려면 반드시 사용합니다.
|
|
269
|
+
- `scopeId`를 직접 지정하거나 자동 생성합니다.
|
|
185
270
|
|
|
186
|
-
|
|
187
|
-
- 품질 레벨 선택 버튼입니다. `text.auto`로 Auto 라벨을 변경할 수 있습니다.
|
|
188
|
-
- `HlsVideo`/`DashVideo`가 로딩한 품질 목록(`playerState.levels`) 기반으로 동작합니다.
|
|
271
|
+
### `usePlayerState`
|
|
189
272
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
- 전체화면 토글 버튼입니다. `options.iosFullscreenNativeMode`로 iOS 대응을 제어합니다.
|
|
273
|
+
- 플레이어 상태를 읽고 패치합니다.
|
|
274
|
+
- 재생 상태, 로딩 상태, 자막/음량 상태, 화질 정보 등을 포함합니다.
|
|
193
275
|
|
|
194
|
-
|
|
195
|
-
- 자막 on/off 버튼입니다. `playerState.hasSubtitle`가 true일 때만 노출됩니다.
|
|
276
|
+
### `usePlayerController`
|
|
196
277
|
|
|
197
|
-
|
|
198
|
-
-
|
|
278
|
+
- 재생 제어 API를 제공합니다.
|
|
279
|
+
- 주요 메소드: `play`, `pause`, `togglePlay`, `seekTo`, `setVolume`, `toggleMute`, `toggleSubtitle`, `selectQualityLevel`, `togglePictureInPicture`, `toggleFullscreen`, `fullscreenOn`, `fullscreenOff` 등.
|
|
199
280
|
|
|
200
|
-
|
|
201
|
-
- 음소거 버튼 + 볼륨 슬라이더를 함께 제공합니다.
|
|
281
|
+
### `useDeviceState`
|
|
202
282
|
|
|
203
|
-
|
|
204
|
-
- 설정 모달 토글 버튼입니다. `playerState.isSettingModal`을 토글합니다.
|
|
283
|
+
- 미디어쿼리 기반으로 `isMobile`, `isPortrait` 상태를 제공합니다.
|
|
205
284
|
|
|
206
|
-
|
|
207
|
-
- Picture-in-Picture 토글 버튼입니다.
|
|
285
|
+
### `usePlayerKeyboardControls`
|
|
208
286
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
-
|
|
212
|
-
- props: `title`, `profileImage`, `profileName`, `createdAt`, `color`.
|
|
287
|
+
- 키보드 제어를 등록합니다.
|
|
288
|
+
- `options.keyboardShortcut`이 `true`일 때만 동작합니다.
|
|
289
|
+
- 단축키: Space(재생/일시정지), 좌/우(10초 이동), F(전체화면), M(음소거)
|
|
213
290
|
|
|
214
|
-
|
|
215
|
-
- 좌/우/중앙 정렬용 빈 공간 레이아웃 컴포넌트입니다.
|
|
216
|
-
- props: `align`(`left`/`right`/`center`), `style`, `children`.
|
|
291
|
+
## 유틸
|
|
217
292
|
|
|
218
|
-
|
|
219
|
-
- 버튼 그룹 래퍼입니다. 내부적으로 `BtnGroup`을 사용합니다.
|
|
220
|
-
- props: `noPadding`, `cap`(간격), `noBg`, `style`.
|
|
293
|
+
- `$util.formatTime(seconds)` 형태로 시간 문자열을 생성합니다.
|
|
221
294
|
|
|
222
|
-
|
|
223
|
-
#### `InitPlayerUi`
|
|
224
|
-
- 포스터 위에 초기 재생 버튼을 띄우는 오버레이입니다.
|
|
225
|
-
- props: `poster`, `options.objectFit`.
|
|
295
|
+
## 개발 명령
|
|
226
296
|
|
|
227
|
-
|
|
228
|
-
|
|
297
|
+
```bash
|
|
298
|
+
pnpm dev
|
|
299
|
+
pnpm build
|
|
300
|
+
pnpm preview
|
|
301
|
+
pnpm lint
|
|
302
|
+
```
|
|
229
303
|
|
|
230
|
-
|
|
231
|
-
- 모바일 더블탭 시킹 오버레이입니다.
|
|
232
|
-
- props:
|
|
233
|
-
- `seekSeconds`: 한번에 이동할 초(기본 10).
|
|
234
|
-
- `doubleTapWindowMs`: 더블탭 인식 시간(기본 300ms).
|
|
235
|
-
- `executeDelayMs`: 시킹 실행 지연(기본 300ms).
|
|
236
|
-
- `onSingleTap`: 단일 탭 콜백.
|
|
304
|
+
## 빌드 산출물
|
|
237
305
|
|
|
238
|
-
|
|
239
|
-
-
|
|
240
|
-
- props:
|
|
241
|
-
- `text`: `{ setting, quality, autoplay, playbackRate, captions, auto, notUse }` 라벨.
|
|
242
|
-
- `options.playRateSetting`: 재생 속도 선택 리스트(예: `[0.5, 1, 1.5, 2]`).
|
|
243
|
-
- `vtt` 또는 `src.vtt`: 자막 리스트.
|
|
244
|
-
- 표시 여부는 `usePlayerState`의 `isSettingModal` 상태로 제어하는 패턴을 권장합니다.
|
|
306
|
+
- ESM: `dist/vpe-react-ui.es.js`
|
|
307
|
+
- UMD: `dist/vpe-react-ui.umd.js`
|
package/package.json
CHANGED
package/dist/vpe-react-ui.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.obtn{background-color:#00000073;aspect-ratio:1/1;width:2.5em;border-radius:500px;display:flex;justify-content:center;align-items:center;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.obtnNoBg{aspect-ratio:1.2/1;width:2.3em;border-radius:500px;display:flex;justify-content:center;align-items:center}.obtn:hover{background-color:#000000a6}.obtnNoBg:hover{background-color:#00000073}.obtn-group{background-color:#00000040;height:2.5em;border-radius:500px;display:flex;justify-content:center;align-items:center;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px)}.obtn-group:hover{background-color:#0000004d}.tra200{transition:all .2s ease}
|
package/dist/vpe-react-ui.es.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import { jsx as f, Fragment as w } from "react/jsx-runtime";
|
|
2
|
-
import * as a from "react";
|
|
3
|
-
import x, { createContext as N, useSyncExternalStore as I, useRef as T, useEffect as Z } from "react";
|
|
4
|
-
var M = { exports: {} }, R = {};
|
|
5
|
-
var b;
|
|
6
|
-
function j() {
|
|
7
|
-
if (b) return R;
|
|
8
|
-
b = 1;
|
|
9
|
-
var t = x.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
|
10
|
-
return R.c = function(e) {
|
|
11
|
-
return t.H.useMemoCache(e);
|
|
12
|
-
}, R;
|
|
13
|
-
}
|
|
14
|
-
var P;
|
|
15
|
-
function B() {
|
|
16
|
-
return P || (P = 1, M.exports = j()), M.exports;
|
|
17
|
-
}
|
|
18
|
-
var g = B();
|
|
19
|
-
const D = /* @__PURE__ */ new Map([
|
|
20
|
-
[
|
|
21
|
-
"bold",
|
|
22
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M200,28H160a20,20,0,0,0-20,20V208a20,20,0,0,0,20,20h40a20,20,0,0,0,20-20V48A20,20,0,0,0,200,28Zm-4,176H164V52h32ZM96,28H56A20,20,0,0,0,36,48V208a20,20,0,0,0,20,20H96a20,20,0,0,0,20-20V48A20,20,0,0,0,96,28ZM92,204H60V52H92Z" }))
|
|
23
|
-
],
|
|
24
|
-
[
|
|
25
|
-
"duotone",
|
|
26
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(
|
|
27
|
-
"path",
|
|
28
|
-
{
|
|
29
|
-
d: "M208,48V208a8,8,0,0,1-8,8H160a8,8,0,0,1-8-8V48a8,8,0,0,1,8-8h40A8,8,0,0,1,208,48ZM96,40H56a8,8,0,0,0-8,8V208a8,8,0,0,0,8,8H96a8,8,0,0,0,8-8V48A8,8,0,0,0,96,40Z",
|
|
30
|
-
opacity: "0.2"
|
|
31
|
-
}
|
|
32
|
-
), /* @__PURE__ */ a.createElement("path", { d: "M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z" }))
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
"fill",
|
|
36
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M216,48V208a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V48a16,16,0,0,1,16-16h40A16,16,0,0,1,216,48ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Z" }))
|
|
37
|
-
],
|
|
38
|
-
[
|
|
39
|
-
"light",
|
|
40
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M200,34H160a14,14,0,0,0-14,14V208a14,14,0,0,0,14,14h40a14,14,0,0,0,14-14V48A14,14,0,0,0,200,34Zm2,174a2,2,0,0,1-2,2H160a2,2,0,0,1-2-2V48a2,2,0,0,1,2-2h40a2,2,0,0,1,2,2ZM96,34H56A14,14,0,0,0,42,48V208a14,14,0,0,0,14,14H96a14,14,0,0,0,14-14V48A14,14,0,0,0,96,34Zm2,174a2,2,0,0,1-2,2H56a2,2,0,0,1-2-2V48a2,2,0,0,1,2-2H96a2,2,0,0,1,2,2Z" }))
|
|
41
|
-
],
|
|
42
|
-
[
|
|
43
|
-
"regular",
|
|
44
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z" }))
|
|
45
|
-
],
|
|
46
|
-
[
|
|
47
|
-
"thin",
|
|
48
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M200,36H160a12,12,0,0,0-12,12V208a12,12,0,0,0,12,12h40a12,12,0,0,0,12-12V48A12,12,0,0,0,200,36Zm4,172a4,4,0,0,1-4,4H160a4,4,0,0,1-4-4V48a4,4,0,0,1,4-4h40a4,4,0,0,1,4,4ZM96,36H56A12,12,0,0,0,44,48V208a12,12,0,0,0,12,12H96a12,12,0,0,0,12-12V48A12,12,0,0,0,96,36Zm4,172a4,4,0,0,1-4,4H56a4,4,0,0,1-4-4V48a4,4,0,0,1,4-4H96a4,4,0,0,1,4,4Z" }))
|
|
49
|
-
]
|
|
50
|
-
]), O = /* @__PURE__ */ new Map([
|
|
51
|
-
[
|
|
52
|
-
"bold",
|
|
53
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z" }))
|
|
54
|
-
],
|
|
55
|
-
[
|
|
56
|
-
"duotone",
|
|
57
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(
|
|
58
|
-
"path",
|
|
59
|
-
{
|
|
60
|
-
d: "M228.23,134.69,84.15,222.81A8,8,0,0,1,72,216.12V39.88a8,8,0,0,1,12.15-6.69l144.08,88.12A7.82,7.82,0,0,1,228.23,134.69Z",
|
|
61
|
-
opacity: "0.2"
|
|
62
|
-
}
|
|
63
|
-
), /* @__PURE__ */ a.createElement("path", { d: "M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z" }))
|
|
64
|
-
],
|
|
65
|
-
[
|
|
66
|
-
"fill",
|
|
67
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z" }))
|
|
68
|
-
],
|
|
69
|
-
[
|
|
70
|
-
"light",
|
|
71
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M231.36,116.19,87.28,28.06a14,14,0,0,0-14.18-.27A13.69,13.69,0,0,0,66,39.87V216.13a13.69,13.69,0,0,0,7.1,12.08,14,14,0,0,0,14.18-.27l144.08-88.13a13.82,13.82,0,0,0,0-23.62Zm-6.26,13.38L81,217.7a2,2,0,0,1-2.06,0,1.78,1.78,0,0,1-1-1.61V39.87a1.78,1.78,0,0,1,1-1.61A2.06,2.06,0,0,1,80,38a2,2,0,0,1,1,.31L225.1,126.43a1.82,1.82,0,0,1,0,3.14Z" }))
|
|
72
|
-
],
|
|
73
|
-
[
|
|
74
|
-
"regular",
|
|
75
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z" }))
|
|
76
|
-
],
|
|
77
|
-
[
|
|
78
|
-
"thin",
|
|
79
|
-
/* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement("path", { d: "M230.32,117.9,86.24,29.79a11.91,11.91,0,0,0-12.17-.23A11.71,11.71,0,0,0,68,39.89V216.11a11.71,11.71,0,0,0,6.07,10.33,11.91,11.91,0,0,0,12.17-.23L230.32,138.1a11.82,11.82,0,0,0,0-20.2Zm-4.18,13.37L82.06,219.39a4,4,0,0,1-4.07.07,3.77,3.77,0,0,1-2-3.35V39.89a3.77,3.77,0,0,1,2-3.35,4,4,0,0,1,4.07.07l144.08,88.12a3.8,3.8,0,0,1,0,6.54Z" }))
|
|
80
|
-
]
|
|
81
|
-
]), U = N({
|
|
82
|
-
color: "currentColor",
|
|
83
|
-
size: "1em",
|
|
84
|
-
weight: "regular",
|
|
85
|
-
mirrored: !1
|
|
86
|
-
}), S = a.forwardRef(
|
|
87
|
-
(t, e) => {
|
|
88
|
-
const {
|
|
89
|
-
alt: n,
|
|
90
|
-
color: l,
|
|
91
|
-
size: i,
|
|
92
|
-
weight: c,
|
|
93
|
-
mirrored: r,
|
|
94
|
-
children: o,
|
|
95
|
-
weights: m,
|
|
96
|
-
...s
|
|
97
|
-
} = t, {
|
|
98
|
-
color: u = "currentColor",
|
|
99
|
-
size: E,
|
|
100
|
-
weight: V = "regular",
|
|
101
|
-
mirrored: d = !1,
|
|
102
|
-
...H
|
|
103
|
-
} = a.useContext(U);
|
|
104
|
-
return /* @__PURE__ */ a.createElement(
|
|
105
|
-
"svg",
|
|
106
|
-
{
|
|
107
|
-
ref: e,
|
|
108
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
109
|
-
width: i ?? E,
|
|
110
|
-
height: i ?? E,
|
|
111
|
-
fill: l ?? u,
|
|
112
|
-
viewBox: "0 0 256 256",
|
|
113
|
-
transform: r || d ? "scale(-1, 1)" : void 0,
|
|
114
|
-
...H,
|
|
115
|
-
...s
|
|
116
|
-
},
|
|
117
|
-
!!n && /* @__PURE__ */ a.createElement("title", null, n),
|
|
118
|
-
o,
|
|
119
|
-
m.get(c ?? V)
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
S.displayName = "IconBase";
|
|
124
|
-
const L = a.forwardRef((t, e) => /* @__PURE__ */ a.createElement(S, { ref: e, ...t, weights: D }));
|
|
125
|
-
L.displayName = "PauseIcon";
|
|
126
|
-
const p = a.forwardRef((t, e) => /* @__PURE__ */ a.createElement(S, { ref: e, ...t, weights: O }));
|
|
127
|
-
p.displayName = "PlayIcon";
|
|
128
|
-
const _ = /* @__PURE__ */ new Map();
|
|
129
|
-
function z(t, e) {
|
|
130
|
-
if (_.has(t))
|
|
131
|
-
return _.get(t);
|
|
132
|
-
const l = {
|
|
133
|
-
value: typeof e == "function" ? e() : e,
|
|
134
|
-
listeners: /* @__PURE__ */ new Set()
|
|
135
|
-
};
|
|
136
|
-
return _.set(t, l), l;
|
|
137
|
-
}
|
|
138
|
-
function q(t, e) {
|
|
139
|
-
const n = g.c(12);
|
|
140
|
-
let l;
|
|
141
|
-
n[0] !== e || n[1] !== t ? (l = z(t, e), n[0] = e, n[1] = t, n[2] = l) : l = n[2];
|
|
142
|
-
const i = l;
|
|
143
|
-
let c;
|
|
144
|
-
n[3] !== i.listeners ? (c = (d) => (i.listeners.add(d), () => i.listeners.delete(d)), n[3] = i.listeners, n[4] = c) : c = n[4];
|
|
145
|
-
const r = c;
|
|
146
|
-
let o;
|
|
147
|
-
n[5] !== i.value ? (o = () => i.value, n[5] = i.value, n[6] = o) : o = n[6];
|
|
148
|
-
const m = o;
|
|
149
|
-
let s;
|
|
150
|
-
n[7] !== i ? (s = (d) => {
|
|
151
|
-
i.value = typeof d == "function" ? d(i.value) : d, i.listeners.forEach(Y);
|
|
152
|
-
}, n[7] = i, n[8] = s) : s = n[8];
|
|
153
|
-
const u = s, E = I(r, m);
|
|
154
|
-
let V;
|
|
155
|
-
return n[9] !== u || n[10] !== E ? (V = [E, u], n[9] = u, n[10] = E, n[11] = V) : V = n[11], V;
|
|
156
|
-
}
|
|
157
|
-
function Y(t) {
|
|
158
|
-
return t();
|
|
159
|
-
}
|
|
160
|
-
const k = "playerState", G = {
|
|
161
|
-
isPlaying: !1,
|
|
162
|
-
initPlay: !1
|
|
163
|
-
};
|
|
164
|
-
function F() {
|
|
165
|
-
const t = g.c(5), [e, n] = q(k, G);
|
|
166
|
-
let l;
|
|
167
|
-
t[0] !== n ? (l = (r) => {
|
|
168
|
-
n((o) => {
|
|
169
|
-
const m = typeof r == "function" ? r(o) : r;
|
|
170
|
-
return {
|
|
171
|
-
...o,
|
|
172
|
-
...m
|
|
173
|
-
};
|
|
174
|
-
});
|
|
175
|
-
}, t[0] = n, t[1] = l) : l = t[1];
|
|
176
|
-
const i = l;
|
|
177
|
-
let c;
|
|
178
|
-
return t[2] !== i || t[3] !== e ? (c = [e, i], t[2] = i, t[3] = e, t[4] = c) : c = t[4], c;
|
|
179
|
-
}
|
|
180
|
-
function K(t) {
|
|
181
|
-
const e = g.c(23), n = T(null), [l, i] = F(), c = t.hlsLib, r = t.options;
|
|
182
|
-
let o;
|
|
183
|
-
e[0] !== c || e[1] !== r || e[2] !== t ? (o = () => {
|
|
184
|
-
const h = n.current, y = t?.src?.file;
|
|
185
|
-
if (!(!h || !y)) {
|
|
186
|
-
if (c?.isSupported?.()) {
|
|
187
|
-
const A = new c({
|
|
188
|
-
lowLatencyMode: r.lowLatencyMode
|
|
189
|
-
});
|
|
190
|
-
return A.attachMedia(h), A.on(c.Events.MEDIA_ATTACHED, () => {
|
|
191
|
-
A.loadSource(y);
|
|
192
|
-
}), A.on(c.Events.ERROR, ($, C) => {
|
|
193
|
-
t.onError && t.onError({
|
|
194
|
-
evt: $,
|
|
195
|
-
data: C
|
|
196
|
-
});
|
|
197
|
-
}), () => {
|
|
198
|
-
A.destroy();
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
h.src = y;
|
|
202
|
-
}
|
|
203
|
-
}, e[0] = c, e[1] = r, e[2] = t, e[3] = o) : o = e[3];
|
|
204
|
-
const m = t?.src?.file;
|
|
205
|
-
let s;
|
|
206
|
-
e[4] !== c || e[5] !== t.onError || e[6] !== m ? (s = [c, m, t.onError], e[4] = c, e[5] = t.onError, e[6] = m, e[7] = s) : s = e[7], Z(o, s);
|
|
207
|
-
let u, E;
|
|
208
|
-
e[8] !== r ? (u = () => {
|
|
209
|
-
const h = n.current;
|
|
210
|
-
if (!h)
|
|
211
|
-
return;
|
|
212
|
-
const y = r?.playbackRate;
|
|
213
|
-
typeof y == "number" && (h.playbackRate = y);
|
|
214
|
-
}, E = [r], e[8] = r, e[9] = u, e[10] = E) : (u = e[9], E = e[10]), Z(u, E);
|
|
215
|
-
let V, d;
|
|
216
|
-
e[11] !== i ? (V = () => {
|
|
217
|
-
const h = n.current;
|
|
218
|
-
if (!h)
|
|
219
|
-
return;
|
|
220
|
-
const y = () => {
|
|
221
|
-
i({
|
|
222
|
-
isPlaying: !0,
|
|
223
|
-
initPlay: !0
|
|
224
|
-
});
|
|
225
|
-
}, A = () => {
|
|
226
|
-
i({
|
|
227
|
-
isPlaying: !1
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
return h.addEventListener("play", y), h.addEventListener("pause", A), () => {
|
|
231
|
-
h.removeEventListener("play", y), h.removeEventListener("pause", A);
|
|
232
|
-
};
|
|
233
|
-
}, d = [i], e[11] = i, e[12] = V, e[13] = d) : (V = e[12], d = e[13]), Z(V, d);
|
|
234
|
-
let H;
|
|
235
|
-
e[14] !== r?.autostart || e[15] !== r?.muted || e[16] !== r?.objectFit || e[17] !== r?.repeat || e[18] !== l || e[19] !== t.src ? (H = t?.src?.file && /* @__PURE__ */ f("video", { playsInline: !0, ref: n, className: "w-full h-full", controls: !1, autoPlay: r?.autostart, muted: r?.muted, loop: r?.repeat, style: {
|
|
236
|
-
background: t.src.poster ? l.initPlay ? "transparent" : `url(${t.src.poster}) center / ${r?.objectFit ?? "contain"} no-repeat` : void 0,
|
|
237
|
-
objectFit: r?.objectFit ?? "contain"
|
|
238
|
-
} }), e[14] = r?.autostart, e[15] = r?.muted, e[16] = r?.objectFit, e[17] = r?.repeat, e[18] = l, e[19] = t.src, e[20] = H) : H = e[20];
|
|
239
|
-
let v;
|
|
240
|
-
return e[21] !== H ? (v = /* @__PURE__ */ f(w, { children: H }), e[21] = H, e[22] = v) : v = e[22], v;
|
|
241
|
-
}
|
|
242
|
-
function W(t) {
|
|
243
|
-
const e = g.c(4);
|
|
244
|
-
let n;
|
|
245
|
-
e[0] !== t.src ? (n = t?.src?.file && /* @__PURE__ */ f("div", { children: t.src.file }), e[0] = t.src, e[1] = n) : n = e[1];
|
|
246
|
-
let l;
|
|
247
|
-
return e[2] !== n ? (l = /* @__PURE__ */ f(w, { children: n }), e[2] = n, e[3] = l) : l = e[3], l;
|
|
248
|
-
}
|
|
249
|
-
function J(t) {
|
|
250
|
-
const e = g.c(4);
|
|
251
|
-
let n;
|
|
252
|
-
e[0] !== t.src ? (n = t?.src?.file && /* @__PURE__ */ f("div", { children: t.src.file }), e[0] = t.src, e[1] = n) : n = e[1];
|
|
253
|
-
let l;
|
|
254
|
-
return e[2] !== n ? (l = /* @__PURE__ */ f(w, { children: n }), e[2] = n, e[3] = l) : l = e[3], l;
|
|
255
|
-
}
|
|
256
|
-
function Q(t) {
|
|
257
|
-
const e = g.c(3);
|
|
258
|
-
let n;
|
|
259
|
-
e[0] === Symbol.for("react.memo_cache_sentinel") ? (n = {
|
|
260
|
-
display: "flex",
|
|
261
|
-
justifyContent: "center",
|
|
262
|
-
alignItems: "center"
|
|
263
|
-
}, e[0] = n) : n = e[0];
|
|
264
|
-
let l;
|
|
265
|
-
return e[1] !== t.children ? (l = /* @__PURE__ */ f("div", { style: n, className: "obtn", children: t.children }), e[1] = t.children, e[2] = l) : l = e[2], l;
|
|
266
|
-
}
|
|
267
|
-
function te(t) {
|
|
268
|
-
const e = g.c(2);
|
|
269
|
-
let n;
|
|
270
|
-
return e[0] !== t ? (n = /* @__PURE__ */ f(K, { ...t }), e[0] = t, e[1] = n) : n = e[1], n;
|
|
271
|
-
}
|
|
272
|
-
function ne(t) {
|
|
273
|
-
const e = g.c(2);
|
|
274
|
-
let n;
|
|
275
|
-
return e[0] !== t ? (n = /* @__PURE__ */ f(W, { ...t }), e[0] = t, e[1] = n) : n = e[1], n;
|
|
276
|
-
}
|
|
277
|
-
function ae(t) {
|
|
278
|
-
const e = g.c(2);
|
|
279
|
-
let n;
|
|
280
|
-
return e[0] !== t ? (n = /* @__PURE__ */ f(J, { ...t }), e[0] = t, e[1] = n) : n = e[1], n;
|
|
281
|
-
}
|
|
282
|
-
function le(t) {
|
|
283
|
-
const e = g.c(6), {
|
|
284
|
-
size: n,
|
|
285
|
-
weight: l,
|
|
286
|
-
color: i
|
|
287
|
-
} = t, c = n === void 0 ? 25 : n, r = l === void 0 ? "fill" : l, o = i === void 0 ? "#ffffff" : i, [m] = F();
|
|
288
|
-
let s;
|
|
289
|
-
e[0] === Symbol.for("react.memo_cache_sentinel") ? (s = {
|
|
290
|
-
background: "transparent",
|
|
291
|
-
border: 0,
|
|
292
|
-
padding: 0,
|
|
293
|
-
lineHeight: "100%",
|
|
294
|
-
display: "flex",
|
|
295
|
-
justifyContent: "center",
|
|
296
|
-
alignItems: "center"
|
|
297
|
-
}, e[0] = s) : s = e[0];
|
|
298
|
-
let u;
|
|
299
|
-
return e[1] !== o || e[2] !== m.isPlaying || e[3] !== c || e[4] !== r ? (u = /* @__PURE__ */ f(Q, { children: /* @__PURE__ */ f("button", { type: "button", style: s, children: m.isPlaying ? /* @__PURE__ */ f(L, { size: c, weight: r, color: o }) : /* @__PURE__ */ f(p, { size: c, weight: r, color: o }) }) }), e[1] = o, e[2] = m.isPlaying, e[3] = c, e[4] = r, e[5] = u) : u = e[5], u;
|
|
300
|
-
}
|
|
301
|
-
function re() {
|
|
302
|
-
const t = g.c(1);
|
|
303
|
-
let e;
|
|
304
|
-
return t[0] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ f("div", { children: "btn2" }), t[0] = e) : e = t[0], e;
|
|
305
|
-
}
|
|
306
|
-
export {
|
|
307
|
-
ne as DashVideo,
|
|
308
|
-
te as HlsVideo,
|
|
309
|
-
ae as Mp4Video,
|
|
310
|
-
le as PlayBtn,
|
|
311
|
-
re as PlayBtn2
|
|
312
|
-
};
|
package/dist/vpe-react-ui.umd.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(h,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],o):(h=typeof globalThis<"u"?globalThis:h||self,o(h.VpeReactUi={},h.React,h.React))})(this,(function(h,o,A){"use strict";function R(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const l=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,l.get?l:{enumerable:!0,get:()=>t[n]})}}return e.default=t,Object.freeze(e)}const a=R(A);var b={exports:{}},_={};var P;function j(){if(P)return _;P=1;var t=A.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;return _.c=function(e){return t.H.useMemoCache(e)},_}var p;function N(){return p||(p=1,b.exports=j()),b.exports}var E=N();const T=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M200,28H160a20,20,0,0,0-20,20V208a20,20,0,0,0,20,20h40a20,20,0,0,0,20-20V48A20,20,0,0,0,200,28Zm-4,176H164V52h32ZM96,28H56A20,20,0,0,0,36,48V208a20,20,0,0,0,20,20H96a20,20,0,0,0,20-20V48A20,20,0,0,0,96,28ZM92,204H60V52H92Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M208,48V208a8,8,0,0,1-8,8H160a8,8,0,0,1-8-8V48a8,8,0,0,1,8-8h40A8,8,0,0,1,208,48ZM96,40H56a8,8,0,0,0-8,8V208a8,8,0,0,0,8,8H96a8,8,0,0,0,8-8V48A8,8,0,0,0,96,40Z",opacity:"0.2"}),a.createElement("path",{d:"M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M216,48V208a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V48a16,16,0,0,1,16-16h40A16,16,0,0,1,216,48ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M200,34H160a14,14,0,0,0-14,14V208a14,14,0,0,0,14,14h40a14,14,0,0,0,14-14V48A14,14,0,0,0,200,34Zm2,174a2,2,0,0,1-2,2H160a2,2,0,0,1-2-2V48a2,2,0,0,1,2-2h40a2,2,0,0,1,2,2ZM96,34H56A14,14,0,0,0,42,48V208a14,14,0,0,0,14,14H96a14,14,0,0,0,14-14V48A14,14,0,0,0,96,34Zm2,174a2,2,0,0,1-2,2H56a2,2,0,0,1-2-2V48a2,2,0,0,1,2-2H96a2,2,0,0,1,2,2Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M200,36H160a12,12,0,0,0-12,12V208a12,12,0,0,0,12,12h40a12,12,0,0,0,12-12V48A12,12,0,0,0,200,36Zm4,172a4,4,0,0,1-4,4H160a4,4,0,0,1-4-4V48a4,4,0,0,1,4-4h40a4,4,0,0,1,4,4ZM96,36H56A12,12,0,0,0,44,48V208a12,12,0,0,0,12,12H96a12,12,0,0,0,12-12V48A12,12,0,0,0,96,36Zm4,172a4,4,0,0,1-4,4H56a4,4,0,0,1-4-4V48a4,4,0,0,1,4-4H96a4,4,0,0,1,4,4Z"}))]]),O=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M228.23,134.69,84.15,222.81A8,8,0,0,1,72,216.12V39.88a8,8,0,0,1,12.15-6.69l144.08,88.12A7.82,7.82,0,0,1,228.23,134.69Z",opacity:"0.2"}),a.createElement("path",{d:"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M231.36,116.19,87.28,28.06a14,14,0,0,0-14.18-.27A13.69,13.69,0,0,0,66,39.87V216.13a13.69,13.69,0,0,0,7.1,12.08,14,14,0,0,0,14.18-.27l144.08-88.13a13.82,13.82,0,0,0,0-23.62Zm-6.26,13.38L81,217.7a2,2,0,0,1-2.06,0,1.78,1.78,0,0,1-1-1.61V39.87a1.78,1.78,0,0,1,1-1.61A2.06,2.06,0,0,1,80,38a2,2,0,0,1,1,.31L225.1,126.43a1.82,1.82,0,0,1,0,3.14Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M230.32,117.9,86.24,29.79a11.91,11.91,0,0,0-12.17-.23A11.71,11.71,0,0,0,68,39.89V216.11a11.71,11.71,0,0,0,6.07,10.33,11.91,11.91,0,0,0,12.17-.23L230.32,138.1a11.82,11.82,0,0,0,0-20.2Zm-4.18,13.37L82.06,219.39a4,4,0,0,1-4.07.07,3.77,3.77,0,0,1-2-3.35V39.89a3.77,3.77,0,0,1,2-3.35,4,4,0,0,1,4.07.07l144.08,88.12a3.8,3.8,0,0,1,0,6.54Z"}))]]),x=A.createContext({color:"currentColor",size:"1em",weight:"regular",mirrored:!1}),S=a.forwardRef((t,e)=>{const{alt:n,color:l,size:c,weight:i,mirrored:r,children:s,weights:d,...u}=t,{color:f="currentColor",size:g,weight:y="regular",mirrored:m=!1,...v}=a.useContext(x);return a.createElement("svg",{ref:e,xmlns:"http://www.w3.org/2000/svg",width:c??g,height:c??g,fill:l??f,viewBox:"0 0 256 256",transform:r||m?"scale(-1, 1)":void 0,...v,...u},!!n&&a.createElement("title",null,n),s,d.get(i??y))});S.displayName="IconBase";const F=a.forwardRef((t,e)=>a.createElement(S,{ref:e,...t,weights:T}));F.displayName="PauseIcon";const L=a.forwardRef((t,e)=>a.createElement(S,{ref:e,...t,weights:O}));L.displayName="PlayIcon";const w=new Map;function I(t,e){if(w.has(t))return w.get(t);const l={value:typeof e=="function"?e():e,listeners:new Set};return w.set(t,l),l}function D(t,e){const n=E.c(12);let l;n[0]!==e||n[1]!==t?(l=I(t,e),n[0]=e,n[1]=t,n[2]=l):l=n[2];const c=l;let i;n[3]!==c.listeners?(i=m=>(c.listeners.add(m),()=>c.listeners.delete(m)),n[3]=c.listeners,n[4]=i):i=n[4];const r=i;let s;n[5]!==c.value?(s=()=>c.value,n[5]=c.value,n[6]=s):s=n[6];const d=s;let u;n[7]!==c?(u=m=>{c.value=typeof m=="function"?m(c.value):m,c.listeners.forEach(B)},n[7]=c,n[8]=u):u=n[8];const f=u,g=A.useSyncExternalStore(r,d);let y;return n[9]!==f||n[10]!==g?(y=[g,f],n[9]=f,n[10]=g,n[11]=y):y=n[11],y}function B(t){return t()}const $="playerState",U={isPlaying:!1,initPlay:!1};function C(){const t=E.c(5),[e,n]=D($,U);let l;t[0]!==n?(l=r=>{n(s=>{const d=typeof r=="function"?r(s):r;return{...s,...d}})},t[0]=n,t[1]=l):l=t[1];const c=l;let i;return t[2]!==c||t[3]!==e?(i=[e,c],t[2]=c,t[3]=e,t[4]=i):i=t[4],i}function q(t){const e=E.c(23),n=A.useRef(null),[l,c]=C(),i=t.hlsLib,r=t.options;let s;e[0]!==i||e[1]!==r||e[2]!==t?(s=()=>{const V=n.current,H=t?.src?.file;if(!(!V||!H)){if(i?.isSupported?.()){const M=new i({lowLatencyMode:r.lowLatencyMode});return M.attachMedia(V),M.on(i.Events.MEDIA_ATTACHED,()=>{M.loadSource(H)}),M.on(i.Events.ERROR,(X,ee)=>{t.onError&&t.onError({evt:X,data:ee})}),()=>{M.destroy()}}V.src=H}},e[0]=i,e[1]=r,e[2]=t,e[3]=s):s=e[3];const d=t?.src?.file;let u;e[4]!==i||e[5]!==t.onError||e[6]!==d?(u=[i,d,t.onError],e[4]=i,e[5]=t.onError,e[6]=d,e[7]=u):u=e[7],A.useEffect(s,u);let f,g;e[8]!==r?(f=()=>{const V=n.current;if(!V)return;const H=r?.playbackRate;typeof H=="number"&&(V.playbackRate=H)},g=[r],e[8]=r,e[9]=f,e[10]=g):(f=e[9],g=e[10]),A.useEffect(f,g);let y,m;e[11]!==c?(y=()=>{const V=n.current;if(!V)return;const H=()=>{c({isPlaying:!0,initPlay:!0})},M=()=>{c({isPlaying:!1})};return V.addEventListener("play",H),V.addEventListener("pause",M),()=>{V.removeEventListener("play",H),V.removeEventListener("pause",M)}},m=[c],e[11]=c,e[12]=y,e[13]=m):(y=e[12],m=e[13]),A.useEffect(y,m);let v;e[14]!==r?.autostart||e[15]!==r?.muted||e[16]!==r?.objectFit||e[17]!==r?.repeat||e[18]!==l||e[19]!==t.src?(v=t?.src?.file&&o.jsx("video",{playsInline:!0,ref:n,className:"w-full h-full",controls:!1,autoPlay:r?.autostart,muted:r?.muted,loop:r?.repeat,style:{background:t.src.poster?l.initPlay?"transparent":`url(${t.src.poster}) center / ${r?.objectFit??"contain"} no-repeat`:void 0,objectFit:r?.objectFit??"contain"}}),e[14]=r?.autostart,e[15]=r?.muted,e[16]=r?.objectFit,e[17]=r?.repeat,e[18]=l,e[19]=t.src,e[20]=v):v=e[20];let Z;return e[21]!==v?(Z=o.jsx(o.Fragment,{children:v}),e[21]=v,e[22]=Z):Z=e[22],Z}function z(t){const e=E.c(4);let n;e[0]!==t.src?(n=t?.src?.file&&o.jsx("div",{children:t.src.file}),e[0]=t.src,e[1]=n):n=e[1];let l;return e[2]!==n?(l=o.jsx(o.Fragment,{children:n}),e[2]=n,e[3]=l):l=e[3],l}function Y(t){const e=E.c(4);let n;e[0]!==t.src?(n=t?.src?.file&&o.jsx("div",{children:t.src.file}),e[0]=t.src,e[1]=n):n=e[1];let l;return e[2]!==n?(l=o.jsx(o.Fragment,{children:n}),e[2]=n,e[3]=l):l=e[3],l}function k(t){const e=E.c(3);let n;e[0]===Symbol.for("react.memo_cache_sentinel")?(n={display:"flex",justifyContent:"center",alignItems:"center"},e[0]=n):n=e[0];let l;return e[1]!==t.children?(l=o.jsx("div",{style:n,className:"obtn",children:t.children}),e[1]=t.children,e[2]=l):l=e[2],l}function G(t){const e=E.c(2);let n;return e[0]!==t?(n=o.jsx(q,{...t}),e[0]=t,e[1]=n):n=e[1],n}function K(t){const e=E.c(2);let n;return e[0]!==t?(n=o.jsx(z,{...t}),e[0]=t,e[1]=n):n=e[1],n}function W(t){const e=E.c(2);let n;return e[0]!==t?(n=o.jsx(Y,{...t}),e[0]=t,e[1]=n):n=e[1],n}function J(t){const e=E.c(6),{size:n,weight:l,color:c}=t,i=n===void 0?25:n,r=l===void 0?"fill":l,s=c===void 0?"#ffffff":c,[d]=C();let u;e[0]===Symbol.for("react.memo_cache_sentinel")?(u={background:"transparent",border:0,padding:0,lineHeight:"100%",display:"flex",justifyContent:"center",alignItems:"center"},e[0]=u):u=e[0];let f;return e[1]!==s||e[2]!==d.isPlaying||e[3]!==i||e[4]!==r?(f=o.jsx(k,{children:o.jsx("button",{type:"button",style:u,children:d.isPlaying?o.jsx(F,{size:i,weight:r,color:s}):o.jsx(L,{size:i,weight:r,color:s})})}),e[1]=s,e[2]=d.isPlaying,e[3]=i,e[4]=r,e[5]=f):f=e[5],f}function Q(){const t=E.c(1);let e;return t[0]===Symbol.for("react.memo_cache_sentinel")?(e=o.jsx("div",{children:"btn2"}),t[0]=e):e=t[0],e}h.DashVideo=K,h.HlsVideo=G,h.Mp4Video=W,h.PlayBtn=J,h.PlayBtn2=Q,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
|