@glitchlab/react-video-player 0.1.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +188 -42
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +55 -1
- package/dist/index.mjs +197 -195
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +4 -1
- package/package.json +102 -86
- package/dist/src/HLSPlayer.d.ts +0 -5
- package/dist/src/VideoPlayerWrapper.d.ts +0 -5
- package/dist/src/index.d.ts +0 -3
- package/dist/src/types/index.d.ts +0 -35
- package/dist/src/utils/icons.d.ts +0 -12
- package/dist/tailwind.config.d.ts +0 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 im-fahad
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,73 +1,113 @@
|
|
|
1
|
-
# react-video-player
|
|
1
|
+
# @glitchlab/react-video-player
|
|
2
2
|
|
|
3
|
-
A lightweight, HLS-capable React video player
|
|
4
|
-
|
|
3
|
+
A lightweight, HLS-capable React video player with a polished overlay UI, device-mode toggle, hover-to-play, and **zero global CSS side-effects**. Works seamlessly with Next.js App Router.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@glitchlab/react-video-player)
|
|
6
|
+
[](https://bundlephobia.com/package/@glitchlab/react-video-player)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
[](#typescript)
|
|
5
9
|
|
|
6
10
|
---
|
|
7
11
|
|
|
8
|
-
##
|
|
12
|
+
## Why this player
|
|
9
13
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- Fully typed
|
|
14
|
+
- **HLS streaming** via `hls.js` with automatic native fallback (Safari)
|
|
15
|
+
- **Next.js App Router compatible** — `"use client"` is preserved in the build
|
|
16
|
+
- **Scoped CSS, no preflight** — all styles live under `.gvp-root`. No `*` resets, no theme tokens leaked into your design system
|
|
17
|
+
- **Device-mode toggle** — flip between desktop (16:9) and mobile (9:16) presets
|
|
18
|
+
- **Hover-to-play** with safe play/pause race handling
|
|
19
|
+
- Tiny: ~3 KB CSS gzipped, ~3 KB JS gzipped
|
|
20
|
+
- Fully typed; SSR-safe
|
|
17
21
|
|
|
18
22
|
---
|
|
19
23
|
|
|
20
24
|
## Installation
|
|
21
25
|
|
|
22
26
|
```bash
|
|
23
|
-
npm install @glitchlab/react-video-player
|
|
27
|
+
npm install @glitchlab/react-video-player hls.js
|
|
28
|
+
# or
|
|
29
|
+
pnpm add @glitchlab/react-video-player hls.js
|
|
30
|
+
# or
|
|
31
|
+
yarn add @glitchlab/react-video-player hls.js
|
|
24
32
|
```
|
|
25
33
|
|
|
26
|
-
> **Peer dependencies:** `react`, `react-dom`, `hls.js
|
|
34
|
+
> **Peer dependencies:** `react >= 18`, `react-dom >= 18`, `hls.js >= 1`
|
|
35
|
+
|
|
36
|
+
Import the stylesheet once at your app entry:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import "@glitchlab/react-video-player/style.css";
|
|
40
|
+
```
|
|
27
41
|
|
|
28
42
|
---
|
|
29
43
|
|
|
30
|
-
##
|
|
44
|
+
## Quick start
|
|
31
45
|
|
|
32
46
|
```tsx
|
|
33
|
-
import {ReactVideoPlayer} from "@glitchlab/react-video-player";
|
|
47
|
+
import { ReactVideoPlayer } from "@glitchlab/react-video-player";
|
|
34
48
|
import "@glitchlab/react-video-player/style.css";
|
|
35
49
|
|
|
36
50
|
export default function App() {
|
|
37
51
|
return (
|
|
38
52
|
<ReactVideoPlayer
|
|
39
|
-
src="https://
|
|
40
|
-
poster="
|
|
53
|
+
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
54
|
+
poster="/images/poster.jpg"
|
|
41
55
|
/>
|
|
42
56
|
);
|
|
43
57
|
}
|
|
44
58
|
```
|
|
45
59
|
|
|
60
|
+
That's the entire surface area you need to start. The player auto-detects `.m3u8` URLs and routes them through `hls.js`; everything else plays natively.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Next.js (App Router)
|
|
65
|
+
|
|
66
|
+
The package preserves the `"use client"` directive in its bundled output, so you can import it directly from a server component:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
// app/page.tsx — server component
|
|
70
|
+
import { ReactVideoPlayer } from "@glitchlab/react-video-player";
|
|
71
|
+
import "@glitchlab/react-video-player/style.css";
|
|
72
|
+
|
|
73
|
+
export default function Page() {
|
|
74
|
+
return (
|
|
75
|
+
<main>
|
|
76
|
+
<ReactVideoPlayer src="/videos/hero.m3u8" poster="/images/hero.jpg" />
|
|
77
|
+
</main>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
No client-component wrapper required.
|
|
83
|
+
|
|
46
84
|
---
|
|
47
85
|
|
|
48
86
|
## Props
|
|
49
87
|
|
|
50
88
|
| Prop | Type | Default | Description |
|
|
51
89
|
|--------------------|---------------------------------------------------|-----------------------------------------|------------------------------------------------------------------------------------------|
|
|
52
|
-
| `src` | `string` | — | **Required.** Video URL. `.m3u8`
|
|
53
|
-
| `poster` | `string` | — | Poster image shown before playback.
|
|
54
|
-
| `showDeviceToggle` | `boolean` | `true` | Show the desktop/mobile toggle pill in the top-left
|
|
90
|
+
| `src` | `string` | — | **Required.** Video URL. `.m3u8` is routed through HLS automatically. |
|
|
91
|
+
| `poster` | `string` | — | Poster image shown before playback starts. |
|
|
92
|
+
| `showDeviceToggle` | `boolean` | `true` | Show the desktop/mobile toggle pill in the top-left. |
|
|
55
93
|
| `defaultDevice` | `"desktop" \| "mobile"` | `"desktop"` | Initial device mode. |
|
|
56
|
-
| `hoverPlay` | `boolean` | `false` | Start
|
|
57
|
-
| `tooltipText` | `string` | — |
|
|
58
|
-
| `onClose` | `() => void` | — | If provided, renders a close button in the top-right
|
|
59
|
-
| `className` | `string` | `""` |
|
|
60
|
-
| `muted` | `boolean` | `true` | Mute the video.
|
|
61
|
-
| `loop` | `boolean` | `false` | Loop
|
|
62
|
-
| `controls` | `boolean` | `false` | Show native browser
|
|
94
|
+
| `hoverPlay` | `boolean` | `false` | Start playback on mouse-enter, pause on mouse-leave. |
|
|
95
|
+
| `tooltipText` | `string` | — | Tooltip text shown above the play button on hover. |
|
|
96
|
+
| `onClose` | `() => void` | — | If provided, renders a close button in the top-right. |
|
|
97
|
+
| `className` | `string` | `""` | Extra class added to the outer container (alongside `.gvp-root`). |
|
|
98
|
+
| `muted` | `boolean` | `true` | Mute the video. Required for autoplay in most browsers. |
|
|
99
|
+
| `loop` | `boolean` | `false` | Loop playback. |
|
|
100
|
+
| `controls` | `boolean` | `false` | Show native browser controls. |
|
|
63
101
|
| `frameMaxWidth` | `{ desktop?: string; mobile?: string }` | `{ desktop: "960px", mobile: "420px" }` | Max width of the player in each device mode. |
|
|
64
|
-
| `aspectRatio` | `{ desktop?: AspectRatio; mobile?: AspectRatio }` | `{ desktop: "16/9", mobile: "9/16" }` | Aspect ratio
|
|
102
|
+
| `aspectRatio` | `{ desktop?: AspectRatio; mobile?: AspectRatio }` | `{ desktop: "16/9", mobile: "9/16" }` | Aspect ratio per device mode. `AspectRatio` is `` `${number}/${number}` ``. |
|
|
103
|
+
| `hlsConfig` | `Hls.HlsConfig` | — | Optional hls.js config. Pass a stable reference (e.g. `useMemo`) to avoid HLS rebuilds. |
|
|
104
|
+
| `children` | `React.ReactNode` | — | Rendered inside the underlying `<video>`. Use for `<track>` elements (captions/subs). |
|
|
65
105
|
|
|
66
106
|
---
|
|
67
107
|
|
|
68
108
|
## Examples
|
|
69
109
|
|
|
70
|
-
### Looping background video
|
|
110
|
+
### Looping background video, no UI chrome
|
|
71
111
|
|
|
72
112
|
```tsx
|
|
73
113
|
<ReactVideoPlayer
|
|
@@ -92,34 +132,140 @@ export default function App() {
|
|
|
92
132
|
### Dismissible player in a modal
|
|
93
133
|
|
|
94
134
|
```tsx
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
135
|
+
function VideoModal({ open, onClose }: { open: boolean; onClose: () => void }) {
|
|
136
|
+
if (!open) return null;
|
|
137
|
+
return (
|
|
138
|
+
<div className="modal-backdrop">
|
|
139
|
+
<ReactVideoPlayer
|
|
140
|
+
src="/videos/walkthrough.m3u8"
|
|
141
|
+
onClose={onClose}
|
|
142
|
+
showDeviceToggle={false}
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
100
147
|
```
|
|
101
148
|
|
|
102
|
-
### Custom aspect ratio and
|
|
149
|
+
### Custom aspect ratio and frame width
|
|
103
150
|
|
|
104
151
|
```tsx
|
|
105
152
|
<ReactVideoPlayer
|
|
106
153
|
src="/videos/portrait.mp4"
|
|
107
154
|
defaultDevice="mobile"
|
|
108
|
-
aspectRatio={{desktop: "4/3", mobile: "9/16"}}
|
|
109
|
-
frameMaxWidth={{desktop: "720px", mobile: "360px"}}
|
|
155
|
+
aspectRatio={{ desktop: "4/3", mobile: "9/16" }}
|
|
156
|
+
frameMaxWidth={{ desktop: "720px", mobile: "360px" }}
|
|
110
157
|
/>
|
|
111
158
|
```
|
|
112
159
|
|
|
160
|
+
### Captions and subtitles
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<ReactVideoPlayer src="/videos/talk.m3u8" controls>
|
|
164
|
+
<track kind="captions" src="/captions/talk.en.vtt" srcLang="en" label="English" default />
|
|
165
|
+
<track kind="subtitles" src="/captions/talk.es.vtt" srcLang="es" label="Spanish" />
|
|
166
|
+
</ReactVideoPlayer>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Custom hls.js configuration
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { useMemo } from "react";
|
|
173
|
+
import { ReactVideoPlayer } from "@glitchlab/react-video-player";
|
|
174
|
+
|
|
175
|
+
export default function LiveStream() {
|
|
176
|
+
const hlsConfig = useMemo(
|
|
177
|
+
() => ({
|
|
178
|
+
enableWorker: true,
|
|
179
|
+
lowLatencyMode: true,
|
|
180
|
+
maxBufferLength: 30,
|
|
181
|
+
}),
|
|
182
|
+
[]
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
return <ReactVideoPlayer src="/videos/live.m3u8" hlsConfig={hlsConfig} />;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
> **Always memoize `hlsConfig`.** A fresh object identity each render tears down and rebuilds the entire HLS instance.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## TypeScript
|
|
194
|
+
|
|
195
|
+
Full type definitions ship with the package. Re-exported types:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import type { ReactVideoPlayerProps, AspectRatio } from "@glitchlab/react-video-player";
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Styling and customization
|
|
204
|
+
|
|
205
|
+
All styles are scoped under `.gvp-root`. The CSS file (~3 KB minified) contains no global resets and no design-token bleed. Override what you need:
|
|
206
|
+
|
|
207
|
+
```css
|
|
208
|
+
.gvp-root {
|
|
209
|
+
border-radius: 8px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.gvp-play {
|
|
213
|
+
background-color: rebeccapurple;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.gvp-toggle-btn.is-active {
|
|
217
|
+
color: deeppink;
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Available class hooks:
|
|
222
|
+
|
|
223
|
+
| Class | Element |
|
|
224
|
+
|-----------------------|-----------------------------------------------|
|
|
225
|
+
| `.gvp-root` | Outer container |
|
|
226
|
+
| `.gvp-video` | Underlying `<video>` element |
|
|
227
|
+
| `.gvp-vignette` | Top vignette overlay |
|
|
228
|
+
| `.gvp-bottom-fade` | Bottom gradient |
|
|
229
|
+
| `.gvp-toggle` | Device-toggle wrapper |
|
|
230
|
+
| `.gvp-toggle-pill` | The pill background |
|
|
231
|
+
| `.gvp-toggle-btn` | Individual toggle button (`.is-active` modifier) |
|
|
232
|
+
| `.gvp-toggle-divider` | Vertical divider between toggle buttons |
|
|
233
|
+
| `.gvp-close` | Top-right close button |
|
|
234
|
+
| `.gvp-play-wrap` | Center play-button container |
|
|
235
|
+
| `.gvp-play` | Play button |
|
|
236
|
+
| `.gvp-tooltip` | Tooltip above play button |
|
|
237
|
+
| `.gvp-icon` | All inline SVG icons |
|
|
238
|
+
|
|
113
239
|
---
|
|
114
240
|
|
|
115
|
-
##
|
|
241
|
+
## SSR
|
|
242
|
+
|
|
243
|
+
The component is SSR-safe. Server output renders the static frame; HLS attaches client-side once the video element mounts. Works with Next.js, Remix, and any Vite-SSR / vanilla SSR setup.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Browser support
|
|
248
|
+
|
|
249
|
+
- Chromium ≥ 88, Firefox ≥ 78, Safari ≥ 14, Edge ≥ 88
|
|
250
|
+
- Native HLS playback on Safari (no `hls.js` cost)
|
|
251
|
+
- Worker-based HLS on browsers with MSE
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Contributing
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
git clone https://github.com/im-fahad/react-video-player.git
|
|
259
|
+
cd react-video-player
|
|
260
|
+
pnpm install
|
|
261
|
+
pnpm test
|
|
262
|
+
pnpm build
|
|
263
|
+
```
|
|
116
264
|
|
|
117
|
-
|
|
118
|
-
supports it. On browsers with native HLS support (e.g. Safari), the video element handles playback directly. You can
|
|
119
|
-
also force HLS mode with the `isHls` prop if the URL doesn't end in `.m3u8`.
|
|
265
|
+
Issues and PRs welcome at <https://github.com/im-fahad/react-video-player/issues>.
|
|
120
266
|
|
|
121
267
|
---
|
|
122
268
|
|
|
123
269
|
## License
|
|
124
270
|
|
|
125
|
-
MIT
|
|
271
|
+
[MIT](./LICENSE) © im-fahad
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
"use
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),s=require("react"),N=require("hls.js");function H(e){var l,o,t="";if(typeof e=="string"||typeof e=="number")t+=e;else if(typeof e=="object")if(Array.isArray(e)){var i=e.length;for(l=0;l<i;l++)e[l]&&(o=H(e[l]))&&(t&&(t+=" "),t+=o)}else for(o in e)e[o]&&(t&&(t+=" "),t+=o);return t}function m(){for(var e,l,o=0,t="",i=arguments.length;o<i;o++)(e=arguments[o])&&(l=H(e))&&(t&&(t+=" "),t+=l);return t}const I=s.forwardRef(({src:e,hlsConfig:l,isHls:o,children:t,...i},v)=>{const C=s.useRef(null),c=s.useRef(null);s.useImperativeHandle(v,()=>C.current);const x=globalThis.window!==void 0&&N.isSupported(),h=!!o||x&&typeof e=="string"&&e.endsWith(".m3u8");return s.useEffect(()=>{if(!e)return;const n=C.current;if(n){for(c.current&&(c.current.destroy(),c.current=null),n.pause(),n.removeAttribute("src");n.firstChild;)n.firstChild.remove();if(h){const a=new N(l);c.current=a,a.attachMedia(n),a.loadSource(e),a.on(N.Events.ERROR,(d,L)=>{L.fatal&&(a.destroy(),c.current=null)})}else n.src=e,n.load();return()=>{for(c.current&&(c.current.destroy(),c.current=null),n.pause(),n.removeAttribute("src");n.firstChild;)n.firstChild.remove();n.load()}}},[e,h,l]),r.jsx("video",{ref:C,...i,children:t})});I.displayName="HLSPlayer";const P="gvp-icon",y=e=>e?`${P} ${e}`:P,O=({className:e})=>r.jsxs("svg",{className:y(e),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[r.jsx("path",{d:"M14 2H10C6.72077 2 5.08116 2 3.91891 2.81382C3.48891 3.1149 3.1149 3.48891 2.81382 3.91891C2 5.08116 2 6.72077 2 10C2 13.2792 2 14.9188 2.81382 16.0811C3.1149 16.5111 3.48891 16.8851 3.91891 17.1862C5.08116 18 6.72077 18 10 18H14C17.2792 18 18.9188 18 20.0811 17.1862C20.5111 16.8851 20.8851 16.5111 21.1862 16.0811C22 14.9188 22 13.2792 22 10C22 6.72077 22 5.08116 21.1862 3.91891C20.8851 3.48891 20.5111 3.1149 20.0811 2.81382C18.9188 2 17.2792 2 14 2Z",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),r.jsx("path",{d:"M11 15H13",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),r.jsx("path",{d:"M14.5 22L14.1845 21.5811C13.4733 20.6369 13.2969 19.1944 13.7468 18M9.5 22L9.8155 21.5811C10.5267 20.6369 10.7031 19.1944 10.2532 18",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),r.jsx("path",{d:"M7 22H17",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}),U=({className:e})=>r.jsxs("svg",{className:y(e),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[r.jsx("path",{d:"M5 9C5 5.70017 5 4.05025 6.02513 3.02513C7.05025 2 8.70017 2 12 2C15.2998 2 16.9497 2 17.9749 3.02513C19 4.05025 19 5.70017 19 9V15C19 18.2998 19 19.9497 17.9749 20.9749C16.9497 22 15.2998 22 12 22C8.70017 22 7.05025 22 6.02513 20.9749C5 19.9497 5 18.2998 5 15V9Z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"}),r.jsx("path",{d:"M11 19H13",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),r.jsx("path",{d:"M9 2L9.089 2.53402C9.28188 3.69129 9.37832 4.26993 9.77519 4.62204C10.1892 4.98934 10.7761 5 12 5C13.2239 5 13.8108 4.98934 14.2248 4.62204C14.6217 4.26993 14.7181 3.69129 14.911 2.53402L15 2",stroke:"currentColor",strokeWidth:"2",strokeLinejoin:"round"})]}),$=({className:e})=>r.jsx("svg",{className:y(e),width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:r.jsx("path",{d:"M6.94994 5.53594L12.1929 0.292938C12.5834 -0.0975275 13.2165 -0.0975279 13.6069 0.292938C13.9974 0.683403 13.9974 1.31647 13.6069 1.70694L8.36394 6.94994L13.6069 12.1929C13.9974 12.5834 13.9974 13.2165 13.6069 13.6069C13.2165 13.9974 12.5834 13.9974 12.1929 13.6069L6.94994 8.36394L1.70694 13.6069C1.31647 13.9974 0.683403 13.9974 0.292938 13.6069C-0.0975279 13.2165 -0.0975277 12.5834 0.292938 12.1929L5.53594 6.94994L0.292938 1.70694C-0.0975279 1.31647 -0.0975279 0.683403 0.292938 0.292938C0.683403 -0.0975279 1.31647 -0.0975277 1.70694 0.292938L6.94994 5.53594Z",fill:"currentColor"})}),J=({className:e})=>r.jsx("svg",{className:y(e),width:"22",height:"22",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:r.jsx("path",{d:"M5.3335 11.45V4.54997C5.3335 4.36108 5.40016 4.20275 5.5335 4.07497C5.66683 3.94719 5.82238 3.8833 6.00016 3.8833C6.05572 3.8833 6.11405 3.89163 6.17516 3.9083C6.23627 3.92497 6.29461 3.94997 6.35016 3.9833L11.7835 7.4333C11.8835 7.49997 11.9585 7.5833 12.0085 7.6833C12.0585 7.7833 12.0835 7.88886 12.0835 7.99997C12.0835 8.11108 12.0585 8.21663 12.0085 8.31663C11.9585 8.41663 11.8835 8.49997 11.7835 8.56663L6.35016 12.0166C6.29461 12.05 6.23627 12.075 6.17516 12.0916C6.11405 12.1083 6.05572 12.1166 6.00016 12.1166C5.82238 12.1166 5.66683 12.0527 5.5335 11.925C5.40016 11.7972 5.3335 11.6389 5.3335 11.45Z",fill:"currentColor"})}),W=({src:e,poster:l,showDeviceToggle:o=!0,defaultDevice:t="desktop",hoverPlay:i=!1,tooltipText:v,onClose:C,className:c="",muted:x=!0,loop:h=!1,controls:n=!1,frameMaxWidth:a,aspectRatio:d,hlsConfig:L,children:R})=>{const g=s.useRef(null),k=s.useRef(null),[p,S]=s.useState(t),[E,f]=s.useState(!1),[B,w]=s.useState(!1),V=s.useMemo(()=>p==="mobile"?(d==null?void 0:d.mobile)??"9/16":(d==null?void 0:d.desktop)??"16/9",[p,d]),Z=s.useMemo(()=>p==="mobile"?(a==null?void 0:a.mobile)??"420px":(a==null?void 0:a.desktop)??"960px",[p,a]),b=s.useCallback(async()=>{const u=g.current;if(u){if(k.current)try{await k.current}catch{}u.pause()}},[]),j=s.useCallback(async()=>{const u=g.current;if(u)try{u.readyState<2&&u.load();const M=u.play();k.current=M,await M,f(!0)}catch{f(!1)}finally{k.current=null}},[]),q=s.useCallback(()=>{i&&j()},[i,j]),D=s.useCallback(()=>{i&&b().then(()=>f(!1))},[i,b]),T=s.useCallback(async()=>{const u=g.current;u&&(u.paused?await j():(await b(),f(!1)))},[j,b]);return r.jsxs("div",{className:m("gvp-root",c),style:{width:Z,aspectRatio:V},onMouseEnter:()=>{w(!0),q()},onMouseLeave:()=>{w(!1),D()},children:[r.jsx(I,{ref:g,src:e,poster:l,muted:x,loop:h,playsInline:!0,preload:"metadata",controls:n,hlsConfig:L,className:"gvp-video",onPlay:()=>f(!0),onPause:()=>f(!1),children:R}),r.jsx("div",{className:"gvp-vignette"}),o&&r.jsx("div",{className:"gvp-toggle",children:r.jsxs("div",{className:"gvp-toggle-pill",children:[r.jsx("button",{type:"button",onClick:()=>S("desktop"),className:m("gvp-toggle-btn",p==="desktop"&&"is-active"),"aria-label":"Desktop view","aria-pressed":p==="desktop",children:r.jsx(O,{})}),r.jsx("div",{className:"gvp-toggle-divider"}),r.jsx("button",{type:"button",onClick:()=>S("mobile"),className:m("gvp-toggle-btn",p==="mobile"&&"is-active"),"aria-label":"Mobile view","aria-pressed":p==="mobile",children:r.jsx(U,{})})]})}),C&&r.jsx("button",{type:"button",onClick:C,className:"gvp-close","aria-label":"Close",children:r.jsx($,{})}),!E&&r.jsx("div",{className:"gvp-play-wrap",children:r.jsxs("button",{type:"button",onClick:()=>void T(),onMouseEnter:()=>w(!0),onMouseLeave:()=>w(!1),className:"gvp-play","aria-label":"Play",children:[r.jsx(J,{}),v&&B&&r.jsx("span",{className:"gvp-tooltip",role:"tooltip",children:v})]})}),r.jsx("div",{className:"gvp-bottom-fade"})]})};exports.ReactVideoPlayer=W;
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs","../src/HLSPlayer.tsx","../src/utils/icons.tsx","../src/VideoPlayerWrapper.tsx"],"sourcesContent":["function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","\"use client\";\n\nimport Hls from \"hls.js\";\nimport React, { useEffect, useImperativeHandle, useRef } from \"react\";\nimport type { HLSPlayerProps } from \"./types\";\n\nexport const HLSPlayer = React.forwardRef<HTMLVideoElement, HLSPlayerProps>(\n ({ src, hlsConfig, isHls, children, ...videoProps }, forwardedRef) => {\n const internalRef = useRef<HTMLVideoElement | null>(null);\n const hlsRef = useRef<Hls | null>(null);\n\n useImperativeHandle(forwardedRef, () => internalRef.current as HTMLVideoElement);\n\n const canUseHlsJs = globalThis.window !== undefined && Hls.isSupported();\n const shouldUseHls =\n Boolean(isHls) || (canUseHlsJs && typeof src === \"string\" && src.endsWith(\".m3u8\"));\n\n useEffect(() => {\n if (!src) return;\n const videoEl = internalRef.current;\n if (!videoEl) return;\n\n // destroy previous\n if (hlsRef.current) {\n hlsRef.current.destroy();\n hlsRef.current = null;\n }\n\n // reset video element\n videoEl.pause();\n videoEl.removeAttribute(\"src\");\n while (videoEl.firstChild) videoEl.firstChild.remove();\n\n if (shouldUseHls) {\n const hls = new Hls(hlsConfig);\n hlsRef.current = hls;\n\n hls.attachMedia(videoEl);\n hls.loadSource(src);\n\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n hls.destroy();\n hlsRef.current = null;\n }\n });\n } else {\n // native playback\n videoEl.src = src;\n videoEl.load();\n }\n\n return () => {\n if (hlsRef.current) {\n hlsRef.current.destroy();\n hlsRef.current = null;\n }\n videoEl.pause();\n videoEl.removeAttribute(\"src\");\n while (videoEl.firstChild) videoEl.firstChild.remove();\n videoEl.load();\n };\n }, [src, shouldUseHls, hlsConfig]);\n\n // Captions are the consumer's responsibility — pass <track> elements as children.\n // NOSONAR: typescript:S4084\n return (\n <video ref={internalRef} {...videoProps}>\n {children}\n </video>\n );\n }\n);\n\nHLSPlayer.displayName = \"HLSPlayer\";\nexport default HLSPlayer;\n","\"use client\";\n\nimport React from \"react\";\n\ntype IconProps = { className?: string };\n\nconst baseClass = \"gvp-icon\";\nconst cls = (extra?: string) => (extra ? `${baseClass} ${extra}` : baseClass);\n\nexport const IconDesktop: React.FC<IconProps> = ({ className }) => (\n <svg\n className={cls(className)}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M14 2H10C6.72077 2 5.08116 2 3.91891 2.81382C3.48891 3.1149 3.1149 3.48891 2.81382 3.91891C2 5.08116 2 6.72077 2 10C2 13.2792 2 14.9188 2.81382 16.0811C3.1149 16.5111 3.48891 16.8851 3.91891 17.1862C5.08116 18 6.72077 18 10 18H14C17.2792 18 18.9188 18 20.0811 17.1862C20.5111 16.8851 20.8851 16.5111 21.1862 16.0811C22 14.9188 22 13.2792 22 10C22 6.72077 22 5.08116 21.1862 3.91891C20.8851 3.48891 20.5111 3.1149 20.0811 2.81382C18.9188 2 17.2792 2 14 2Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M11 15H13\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M14.5 22L14.1845 21.5811C13.4733 20.6369 13.2969 19.1944 13.7468 18M9.5 22L9.8155 21.5811C10.5267 20.6369 10.7031 19.1944 10.2532 18\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path d=\"M7 22H17\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport const IconMobile: React.FC<IconProps> = ({ className }) => (\n <svg\n className={cls(className)}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5 9C5 5.70017 5 4.05025 6.02513 3.02513C7.05025 2 8.70017 2 12 2C15.2998 2 16.9497 2 17.9749 3.02513C19 4.05025 19 5.70017 19 9V15C19 18.2998 19 19.9497 17.9749 20.9749C16.9497 22 15.2998 22 12 22C8.70017 22 7.05025 22 6.02513 20.9749C5 19.9497 5 18.2998 5 15V9Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M11 19H13\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M9 2L9.089 2.53402C9.28188 3.69129 9.37832 4.26993 9.77519 4.62204C10.1892 4.98934 10.7761 5 12 5C13.2239 5 13.8108 4.98934 14.2248 4.62204C14.6217 4.26993 14.7181 3.69129 14.911 2.53402L15 2\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport const IconX: React.FC<IconProps> = ({ className }) => (\n <svg\n className={cls(className)}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.94994 5.53594L12.1929 0.292938C12.5834 -0.0975275 13.2165 -0.0975279 13.6069 0.292938C13.9974 0.683403 13.9974 1.31647 13.6069 1.70694L8.36394 6.94994L13.6069 12.1929C13.9974 12.5834 13.9974 13.2165 13.6069 13.6069C13.2165 13.9974 12.5834 13.9974 12.1929 13.6069L6.94994 8.36394L1.70694 13.6069C1.31647 13.9974 0.683403 13.9974 0.292938 13.6069C-0.0975279 13.2165 -0.0975277 12.5834 0.292938 12.1929L5.53594 6.94994L0.292938 1.70694C-0.0975279 1.31647 -0.0975279 0.683403 0.292938 0.292938C0.683403 -0.0975279 1.31647 -0.0975277 1.70694 0.292938L6.94994 5.53594Z\"\n fill=\"currentColor\"\n />\n </svg>\n);\n\nexport const IconPlay: React.FC<IconProps> = ({ className }) => (\n <svg\n className={cls(className)}\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.3335 11.45V4.54997C5.3335 4.36108 5.40016 4.20275 5.5335 4.07497C5.66683 3.94719 5.82238 3.8833 6.00016 3.8833C6.05572 3.8833 6.11405 3.89163 6.17516 3.9083C6.23627 3.92497 6.29461 3.94997 6.35016 3.9833L11.7835 7.4333C11.8835 7.49997 11.9585 7.5833 12.0085 7.6833C12.0585 7.7833 12.0835 7.88886 12.0835 7.99997C12.0835 8.11108 12.0585 8.21663 12.0085 8.31663C11.9585 8.41663 11.8835 8.49997 11.7835 8.56663L6.35016 12.0166C6.29461 12.05 6.23627 12.075 6.17516 12.0916C6.11405 12.1083 6.05572 12.1166 6.00016 12.1166C5.82238 12.1166 5.66683 12.0527 5.5335 11.925C5.40016 11.7972 5.3335 11.6389 5.3335 11.45Z\"\n fill=\"currentColor\"\n />\n </svg>\n);\n","\"use client\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useMemo, useRef, useState } from \"react\";\nimport { HLSPlayer } from \"./HLSPlayer\";\nimport type { DeviceMode, VideoPlayerWrapperProps } from \"./types\";\nimport { IconDesktop, IconMobile, IconPlay, IconX } from \"./utils/icons\";\n\nexport const VideoPlayerWrapper: React.FC<VideoPlayerWrapperProps> = ({\n src,\n poster,\n showDeviceToggle = true,\n defaultDevice = \"desktop\",\n hoverPlay = false,\n tooltipText,\n onClose,\n className = \"\",\n muted = true,\n loop = false,\n controls = false,\n frameMaxWidth: customFrameMaxWidth,\n aspectRatio: customAspectRatio,\n hlsConfig,\n children,\n}) => {\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const playPromiseRef = useRef<Promise<void> | null>(null);\n\n const [device, setDevice] = useState<DeviceMode>(defaultDevice);\n const [isPlaying, setIsPlaying] = useState(false);\n const [showTooltip, setShowTooltip] = useState(false);\n\n const aspectRatio = useMemo(() => {\n return device === \"mobile\"\n ? (customAspectRatio?.mobile ?? \"9/16\")\n : (customAspectRatio?.desktop ?? \"16/9\");\n }, [device, customAspectRatio]);\n\n const frameMaxWidth = useMemo(() => {\n return device === \"mobile\"\n ? (customFrameMaxWidth?.mobile ?? \"420px\")\n : (customFrameMaxWidth?.desktop ?? \"960px\");\n }, [device, customFrameMaxWidth]);\n\n const safePause = useCallback(async () => {\n const el = videoRef.current;\n if (!el) return;\n if (playPromiseRef.current) {\n try {\n await playPromiseRef.current;\n } catch {\n /* play was interrupted; nothing to await */\n }\n }\n el.pause();\n }, []);\n\n const safePlay = useCallback(async () => {\n const el = videoRef.current;\n if (!el) return;\n try {\n if (el.readyState < 2) el.load();\n const p = el.play();\n playPromiseRef.current = p;\n await p;\n setIsPlaying(true);\n } catch {\n setIsPlaying(false);\n } finally {\n playPromiseRef.current = null;\n }\n }, []);\n\n const hoverStart = useCallback(() => {\n if (!hoverPlay) return;\n void safePlay();\n }, [hoverPlay, safePlay]);\n\n const hoverStop = useCallback(() => {\n if (!hoverPlay) return;\n void safePause().then(() => setIsPlaying(false));\n }, [hoverPlay, safePause]);\n\n const togglePlay = useCallback(async () => {\n const el = videoRef.current;\n if (!el) return;\n if (el.paused) {\n await safePlay();\n } else {\n await safePause();\n setIsPlaying(false);\n }\n }, [safePlay, safePause]);\n\n return (\n // The mouse handlers are a progressive enhancement (hoverPlay + tooltip).\n // Keyboard/click users reach the same actions via the inner <button> elements,\n // so the outer container is intentionally non-interactive at the role level.\n // NOSONAR: typescript:S6848\n <div\n className={clsx(\"gvp-root\", className)}\n style={{ width: frameMaxWidth, aspectRatio }}\n onMouseEnter={() => {\n setShowTooltip(true);\n hoverStart();\n }}\n onMouseLeave={() => {\n setShowTooltip(false);\n hoverStop();\n }}\n >\n <HLSPlayer\n ref={videoRef}\n src={src}\n poster={poster}\n muted={muted}\n loop={loop}\n playsInline\n preload=\"metadata\"\n controls={controls}\n hlsConfig={hlsConfig}\n className=\"gvp-video\"\n onPlay={() => setIsPlaying(true)}\n onPause={() => setIsPlaying(false)}\n >\n {children}\n </HLSPlayer>\n\n <div className=\"gvp-vignette\" />\n\n {showDeviceToggle && (\n <div className=\"gvp-toggle\">\n <div className=\"gvp-toggle-pill\">\n <button\n type=\"button\"\n onClick={() => setDevice(\"desktop\")}\n className={clsx(\n \"gvp-toggle-btn\",\n device === \"desktop\" && \"is-active\"\n )}\n aria-label=\"Desktop view\"\n aria-pressed={device === \"desktop\"}\n >\n <IconDesktop />\n </button>\n\n <div className=\"gvp-toggle-divider\" />\n\n <button\n type=\"button\"\n onClick={() => setDevice(\"mobile\")}\n className={clsx(\n \"gvp-toggle-btn\",\n device === \"mobile\" && \"is-active\"\n )}\n aria-label=\"Mobile view\"\n aria-pressed={device === \"mobile\"}\n >\n <IconMobile />\n </button>\n </div>\n </div>\n )}\n\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n className=\"gvp-close\"\n aria-label=\"Close\"\n >\n <IconX />\n </button>\n )}\n\n {!isPlaying && (\n <div className=\"gvp-play-wrap\">\n <button\n type=\"button\"\n onClick={() => void togglePlay()}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n className=\"gvp-play\"\n aria-label=\"Play\"\n >\n <IconPlay />\n {tooltipText && showTooltip && (\n <span className=\"gvp-tooltip\" role=\"tooltip\">\n {tooltipText}\n </span>\n )}\n </button>\n </div>\n )}\n\n <div className=\"gvp-bottom-fade\" />\n </div>\n );\n};\n\nexport default VideoPlayerWrapper;\n"],"names":["r","t","f","n","o","clsx","HLSPlayer","React","src","hlsConfig","isHls","children","videoProps","forwardedRef","internalRef","useRef","hlsRef","useImperativeHandle","canUseHlsJs","Hls","shouldUseHls","useEffect","videoEl","hls","_evt","data","baseClass","cls","extra","IconDesktop","className","jsxs","jsx","IconMobile","IconX","IconPlay","VideoPlayerWrapper","poster","showDeviceToggle","defaultDevice","hoverPlay","tooltipText","onClose","muted","loop","controls","customFrameMaxWidth","customAspectRatio","videoRef","playPromiseRef","device","setDevice","useState","isPlaying","setIsPlaying","showTooltip","setShowTooltip","aspectRatio","useMemo","frameMaxWidth","safePause","useCallback","el","safePlay","p","hoverStart","hoverStop","togglePlay"],"mappings":"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","x_google_ignoreList":[0]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,55 @@
|
|
|
1
|
-
|
|
1
|
+
import { default as default_2 } from 'react';
|
|
2
|
+
import { HlsConfig } from 'hls.js';
|
|
3
|
+
|
|
4
|
+
declare type AspectRatio = `${number}/${number}`;
|
|
5
|
+
|
|
6
|
+
declare type DeviceMode = "desktop" | "mobile";
|
|
7
|
+
|
|
8
|
+
export declare const ReactVideoPlayer: default_2.FC<ReactVideoPlayerProps>;
|
|
9
|
+
|
|
10
|
+
export declare interface ReactVideoPlayerProps {
|
|
11
|
+
/** Video source URL. `.m3u8` URLs are routed through hls.js automatically. */
|
|
12
|
+
src: string;
|
|
13
|
+
/** Poster image shown before playback. */
|
|
14
|
+
poster?: string;
|
|
15
|
+
/** Show the desktop/mobile toggle pill in the top-left. Defaults to `true`. */
|
|
16
|
+
showDeviceToggle?: boolean;
|
|
17
|
+
/** Initial device mode. Defaults to `"desktop"`. */
|
|
18
|
+
defaultDevice?: DeviceMode;
|
|
19
|
+
/** Start playback on mouse enter, pause on mouse leave. Defaults to `false`. */
|
|
20
|
+
hoverPlay?: boolean;
|
|
21
|
+
/** Text shown in a tooltip above the play button. */
|
|
22
|
+
tooltipText?: string;
|
|
23
|
+
/** When provided, renders a close button in the top-right that calls this callback. */
|
|
24
|
+
onClose?: () => void;
|
|
25
|
+
/** Extra class name applied to the outer container. */
|
|
26
|
+
className?: string;
|
|
27
|
+
/** Mute the video. Defaults to `true`. */
|
|
28
|
+
muted?: boolean;
|
|
29
|
+
/** Loop playback. Defaults to `false`. */
|
|
30
|
+
loop?: boolean;
|
|
31
|
+
/** Show native browser controls. Defaults to `false`. */
|
|
32
|
+
controls?: boolean;
|
|
33
|
+
/** Maximum width of the player in each device mode. */
|
|
34
|
+
frameMaxWidth?: {
|
|
35
|
+
desktop?: string;
|
|
36
|
+
mobile?: string;
|
|
37
|
+
};
|
|
38
|
+
/** Aspect ratio in each device mode. */
|
|
39
|
+
aspectRatio?: {
|
|
40
|
+
desktop?: AspectRatio;
|
|
41
|
+
mobile?: AspectRatio;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Optional hls.js configuration. Pass a stable reference (e.g. `useMemo`)
|
|
45
|
+
* to avoid tearing down and rebuilding the HLS instance on each render.
|
|
46
|
+
*/
|
|
47
|
+
hlsConfig?: HlsConfig;
|
|
48
|
+
/**
|
|
49
|
+
* Children rendered inside the underlying `<video>` element. Use this to
|
|
50
|
+
* supply `<track>` elements for captions, subtitles, etc.
|
|
51
|
+
*/
|
|
52
|
+
children?: default_2.ReactNode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { }
|