@tiwz/react-video-player 1.1.9 โ 2.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/README.md +69 -50
- package/dist/fonts/Kodchasan.ttf +0 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -7,15 +7,18 @@ A modern, fully-featured, and mobile-friendly React video player component with
|
|
|
7
7
|
## โจ Features
|
|
8
8
|
|
|
9
9
|
- ๐ฎ Custom video controls (no native controls UI)
|
|
10
|
-
- ๐ฑ Mobile optimized (double-tap to seek ยฑ10s)
|
|
10
|
+
- ๐ฑ Mobile optimized (double-tap to seek ยฑ10s, touch to toggle controls)
|
|
11
11
|
- โจ๏ธ Keyboard shortcuts support (desktop)
|
|
12
12
|
- ๐ฅ Fullscreen & Picture-in-Picture (PiP)
|
|
13
13
|
- ๐ Volume control + mute toggle
|
|
14
|
+
- ๐ฏ Multi-quality source switching (resumes from same timestamp)
|
|
15
|
+
- โก Playback speed control (0.25x โ 4x)
|
|
14
16
|
- ๐ Seek bar with buffered progress indicator
|
|
15
17
|
- ๐ Smooth UX with throttled interactions
|
|
16
|
-
- ๐ก Auto
|
|
18
|
+
- ๐ก Auto-hide controls on inactivity
|
|
17
19
|
- ๐งญ Landscape lock on fullscreen (mobile)
|
|
18
|
-
-
|
|
20
|
+
- ๐ Loading indicator on buffering
|
|
21
|
+
- ๐งฉ Fully typed with TypeScript
|
|
19
22
|
|
|
20
23
|
---
|
|
21
24
|
|
|
@@ -24,15 +27,11 @@ A modern, fully-featured, and mobile-friendly React video player component with
|
|
|
24
27
|
```bash
|
|
25
28
|
npm install @tiwz/react-video-player
|
|
26
29
|
```
|
|
27
|
-
|
|
28
30
|
or
|
|
29
|
-
|
|
30
31
|
```bash
|
|
31
32
|
bun add @tiwz/react-video-player
|
|
32
33
|
```
|
|
33
|
-
|
|
34
34
|
or
|
|
35
|
-
|
|
36
35
|
```bash
|
|
37
36
|
yarn add @tiwz/react-video-player
|
|
38
37
|
```
|
|
@@ -43,7 +42,7 @@ yarn add @tiwz/react-video-player
|
|
|
43
42
|
|
|
44
43
|
```tsx
|
|
45
44
|
import { VideoPlayer } from '@tiwz/react-video-player'
|
|
46
|
-
import '@tiwz/react-video-player/
|
|
45
|
+
import '@tiwz/react-video-player/style.css'
|
|
47
46
|
|
|
48
47
|
export default function App() {
|
|
49
48
|
return (
|
|
@@ -57,19 +56,41 @@ export default function App() {
|
|
|
57
56
|
|
|
58
57
|
---
|
|
59
58
|
|
|
60
|
-
## Video Types
|
|
61
|
-
```ts
|
|
62
|
-
type VideoTypes = 'video/mp4' | 'video/ogg' | 'video/webm' |'application/vnd.apple.mpegurl' | 'application/x-mpegURL'
|
|
63
|
-
```
|
|
64
|
-
|
|
65
59
|
## ๐งฉ Props
|
|
60
|
+
|
|
66
61
|
### VideoPlayerProps
|
|
67
62
|
|
|
68
63
|
| Prop | Type | Required | Description |
|
|
69
|
-
|
|
70
|
-
| `
|
|
71
|
-
| `title` | `string` | โ | Video title
|
|
72
|
-
| `
|
|
64
|
+
|------|------|----------|-------------|
|
|
65
|
+
| `source` | `string \| VideoSourceQuality[]` | โ
| Single URL or array of quality sources |
|
|
66
|
+
| `title` | `string` | โ | Video title shown in top bar |
|
|
67
|
+
| `poster` | `string` | โ | Thumbnail image shown before playback |
|
|
68
|
+
|
|
69
|
+
### VideoSourceQuality
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
type VideoSourceQuality = {
|
|
73
|
+
src: string // Video URL
|
|
74
|
+
quality: number // e.g. 1080, 720, 480. Use 0 for Auto
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Example with multiple qualities:**
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<VideoPlayer
|
|
82
|
+
title="My Video"
|
|
83
|
+
poster="/thumbnail.jpg"
|
|
84
|
+
source={[
|
|
85
|
+
{ src: '/video-1080p.mp4', quality: 1080 },
|
|
86
|
+
{ src: '/video-720p.mp4', quality: 720 },
|
|
87
|
+
{ src: '/video-480p.mp4', quality: 480 },
|
|
88
|
+
{ src: '/video-auto.mp4', quality: 0 }, // Auto
|
|
89
|
+
]}
|
|
90
|
+
/>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> Quality sources are automatically sorted highest to lowest. Switching quality resumes from the same timestamp.
|
|
73
94
|
|
|
74
95
|
---
|
|
75
96
|
|
|
@@ -78,22 +99,21 @@ type VideoTypes = 'video/mp4' | 'video/ogg' | 'video/webm' |'application/vnd.app
|
|
|
78
99
|
### Desktop
|
|
79
100
|
|
|
80
101
|
| Action | Control |
|
|
81
|
-
|
|
82
|
-
| Play / Pause | Click center
|
|
83
|
-
| Seek backward |
|
|
84
|
-
| Seek forward |
|
|
85
|
-
|
|
|
86
|
-
| Picture-in-Picture | P |
|
|
87
|
-
|
|
88
|
-
---
|
|
102
|
+
|--------|---------|
|
|
103
|
+
| Play / Pause | Click center or `Space` |
|
|
104
|
+
| Seek backward 10s | `โ` Arrow |
|
|
105
|
+
| Seek forward 10s | `โ` Arrow |
|
|
106
|
+
| Toggle fullscreen | `F` |
|
|
107
|
+
| Toggle Picture-in-Picture | `P` |
|
|
89
108
|
|
|
90
109
|
### Mobile
|
|
91
110
|
|
|
92
111
|
| Gesture | Action |
|
|
93
|
-
|
|
94
|
-
| Single
|
|
95
|
-
| Double
|
|
96
|
-
| Double
|
|
112
|
+
|---------|--------|
|
|
113
|
+
| Single tap | Show / hide controls |
|
|
114
|
+
| Double tap left | Seek backward 10s |
|
|
115
|
+
| Double tap right | Seek forward 10s |
|
|
116
|
+
| Consecutive taps | Stacked seek (ยฑ20s, ยฑ30s, ...) |
|
|
97
117
|
|
|
98
118
|
---
|
|
99
119
|
|
|
@@ -101,49 +121,48 @@ type VideoTypes = 'video/mp4' | 'video/ogg' | 'video/webm' |'application/vnd.app
|
|
|
101
121
|
|
|
102
122
|
Supports all modern browsers including:
|
|
103
123
|
|
|
104
|
-
- Chrome
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
- Safari
|
|
108
|
-
- Mobile Safari
|
|
109
|
-
- Chrome Android
|
|
124
|
+
- Chrome / Edge / Firefox
|
|
125
|
+
- Safari (desktop)
|
|
126
|
+
- Mobile Safari / Chrome Android
|
|
110
127
|
|
|
111
|
-
Includes automatic **orientation lock** for landscape videos on mobile.
|
|
128
|
+
Includes automatic **orientation lock** to landscape for landscape videos on mobile.
|
|
112
129
|
|
|
113
130
|
---
|
|
114
131
|
|
|
115
132
|
## ๐บ Picture-in-Picture (PiP)
|
|
116
133
|
|
|
117
|
-
Automatically enables PiP when supported by the browser.
|
|
118
|
-
|
|
119
134
|
Works on:
|
|
120
135
|
|
|
121
|
-
- Chrome
|
|
122
|
-
- Edge
|
|
136
|
+
- Chrome / Edge
|
|
123
137
|
- Safari (desktop & iPadOS)
|
|
124
138
|
|
|
139
|
+
> Automatically resumes playback when entering PiP if the video is paused.
|
|
140
|
+
|
|
125
141
|
---
|
|
126
142
|
|
|
127
143
|
## โก Performance
|
|
128
144
|
|
|
129
|
-
- Throttled mouse movement
|
|
130
|
-
- Optimized re-rendering
|
|
131
|
-
-
|
|
145
|
+
- Throttled mouse movement (200ms)
|
|
146
|
+
- Optimized re-rendering via `useReducer` + `useRef`
|
|
147
|
+
- Stale closure prevention with refs for hot-path callbacks
|
|
148
|
+
- Smart seek stacking with auto-reset
|
|
132
149
|
- Minimal event listeners
|
|
133
150
|
|
|
134
151
|
---
|
|
135
152
|
|
|
136
153
|
## ๐งช Browser Support
|
|
137
154
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
155
|
+
| Browser | Fullscreen | PiP | Orientation Lock |
|
|
156
|
+
|---------|-----------|-----|-----------------|
|
|
157
|
+
| Chrome | โ
| โ
| โ
|
|
|
158
|
+
| Edge | โ
| โ
| โ
|
|
|
159
|
+
| Firefox | โ
| โ
| โ ๏ธ Partial |
|
|
160
|
+
| Safari (desktop) | โ
| โ
| โ |
|
|
161
|
+
| Mobile Safari | โ
| โ
(iPadOS) | โ
|
|
|
162
|
+
| Chrome Android | โ
| โ
| โ
|
|
|
144
163
|
|
|
145
164
|
---
|
|
146
165
|
|
|
147
166
|
## ๐ License
|
|
148
167
|
|
|
149
|
-
MIT ยฉ tiwz
|
|
168
|
+
MIT ยฉ 2026 tiwz
|
|
Binary file
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
@font-face{font-display:swap;font-family:BasePlayer;font-style:normal;font-weight:400;src:url(fonts/Kodchasan.ttf) format("truetype")}.style-module_PlayerButton__3pLMQ{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;border-radius:5px;display:flex;height:30px;justify-content:center;transition:background-color .2s;width:30px}.style-module_PlayerDesktop__ccJTe .style-module_PlayerButton__3pLMQ:hover{background-color:#00b2ff;cursor:pointer}.style-module_PlayerWrapper__37Xpc,.style-module_PlayerWrapper__37Xpc *,.style-module_PlayerWrapper__37Xpc :after,.style-module_PlayerWrapper__37Xpc :before{box-sizing:border-box;color:#fff;font-family:BasePlayer,sans-serif;font-optical-sizing:auto;font-style:normal;font-variation-settings:"wdth" 100,"YTLC" 500;font-weight:400;margin:0;padding:0}.style-module_PlayerWrapper__37Xpc{align-items:center;aspect-ratio:16/9;background-color:#000;cursor:none;display:flex;justify-content:center;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.style-module_PlayerVideo__NkoX3{height:100%;max-height:100%;max-width:100%;width:100%}.style-module_PlayerControls__IyMmM{background-color:#0000;display:flex;flex-direction:column;height:100%;left:0;opacity:0;position:absolute;top:0;transition:background-color .4s ease;visibility:hidden;width:100%}.style-module_PlayerControls__IyMmM.style-module_PlayerShown__uVIfu{background-color:#0006;cursor:default;opacity:1;visibility:visible}.style-module_PlayerPanelTop__x02Dp{align-items:center;display:flex;height:50px;padding-inline:14px}.style-module_PlayerTitle__yTvNu{flex:1;font-size:12pt;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.style-module_PlayerPanelCenter__y8jR0{display:flex;flex:1}.style-module_PlayerSeekArea__z-qY-{align-items:center;display:flex;flex:1;height:100%;justify-content:center}.style-module_PlayerPanelBottom__bdhhD{align-items:center;display:flex;gap:10px;height:50px;padding-inline:14px;position:relative}.style-module_PlayerCurrentTime__IaolO,.style-module_PlayerDurationTime__uCgjW{font-family:monospace;font-size:13pt;padding-inline:4px}.style-module_PlayerVolume__r7ll8{align-items:center;display:flex;gap:6px;padding-right:5px}.style-module_PlayerVolumeZone__7LHeR{align-items:center;display:flex;height:4px;position:relative;width:70px}.style-module_PlayerRangeVolume__8XBa1{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:4px;width:100%}.style-module_PlayerSeekTime__SEypx{flex:1;height:4px;position:relative}.style-module_PlayerHoverTime__iBu1D{background-color:#fff;border-radius:99px;color:#000;font-family:monospace;font-size:10pt;left:var(--player-hover-position);padding:2px 8px;position:absolute;top:-34px;transform:translateX(-50%)}.style-module_PlayerHoverTime__iBu1D:before{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #fff;content:"";height:0;left:50%;position:absolute;top:99%;transform:translateX(-50%);width:0}.style-module_PlayerRangeTime__QVr8d,.style-module_PlayerRangeVolume__8XBa1{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;background-image:linear-gradient(to right,#00b2ff var(--player-time-position),#fffa var(--player-time-position),#fffa var(--player-buffer-position),#fff6 var(--player-buffer-position));border-radius:4px;cursor:pointer;display:flex;height:100%;width:100%}.style-module_PlayerRangeTime__QVr8d::-webkit-slider-thumb,.style-module_PlayerRangeVolume__8XBa1::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;border:0;height:0;width:0}.style-module_PlayerRangeTime__QVr8d::-moz-range-thumb,.style-module_PlayerRangeVolume__8XBa1::-moz-range-thumb{-moz-appearance:none;appearance:none;border:0;height:0;width:0}.style-module_PlayerRangeTime__QVr8d::-ms-thumb,.style-module_PlayerRangeVolume__8XBa1::-ms-thumb{appearance:none;border:0;height:0;width:0}.style-module_PlayerRangeThumb__J5IcV{background-color:#fff;border-radius:11px;height:12px;left:var(--player-thumb-position);pointer-events:none;position:absolute;top:-4px;transform:translateX(-50%);transition:box-shadow .2s;width:12px}.style-module_PlayerRangeTime__QVr8d:hover+.style-module_PlayerRangeThumb__J5IcV,.style-module_PlayerRangeVolume__8XBa1:hover+.style-module_PlayerRangeThumb__J5IcV{box-shadow:0 0 1px 3px hsla(0,0%,100%,.28)}.style-module_PlayerCenter__qLy3K,.style-module_PlayerLoading__PBiIH{cursor:pointer;height:60px;left:50%;padding:2px;position:absolute;top:50%;transform:translate(-50%,-50%);width:60px}.style-module_PlayerLoading__PBiIH{height:80px;width:80px}.style-module_PlayerSetting__BhP11{background-color:#0006;cursor:default;height:100%;left:0;position:absolute;top:0;width:100%}.style-module_PlayerSettingPanelQuality__4UQId,.style-module_PlayerSettingPanelSpeed__ABgXy,.style-module_PlayerSettingPanel__tZE0z{background-color:#fff;border-radius:10px;bottom:20px;display:flex;flex-direction:column;gap:4px;left:50%;max-width:80%;padding:10px 4px;position:absolute;transform:translateX(-50%);width:240px}.style-module_PlayerSettingPanelQuality__4UQId *,.style-module_PlayerSettingPanelSpeed__ABgXy *,.style-module_PlayerSettingPanel__tZE0z *{color:#000}.style-module_PlayerSettingPanelQuality__4UQId{max-height:calc(100% - 40px)}.style-module_PlayerSettingList__KEYZR{align-items:center;border-radius:8px;cursor:pointer;display:flex;font-size:14pt;gap:8px;padding:6px 14px}.style-module_PlayerSettingDisplay__-yFqd{display:flex;flex:1;justify-content:space-between}.style-module_PlayerButtonCursor__4PyXl{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#eee;border:0;border-radius:55px;cursor:pointer;display:flex;height:30px;justify-content:center;width:30px}.style-module_PlayerSpeedShow__u1NIt{font-size:14pt;padding-block:4px;text-align:center;width:100%}.style-module_PlayerPlayback__EZYH2{align-items:center;display:flex;gap:8px;padding-inline:8px}.style-module_PlayerRangeSpeed__ElauL{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:linear-gradient(to right,#000 var(--spped-thumb-position),#0006 var(--spped-thumb-position));border-radius:4px;flex:1;height:4px}.style-module_PlayerRangeSpeed__ElauL::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#000;border-radius:50%;cursor:pointer;height:12px;width:12px}.style-module_PlayerRangeSpeed__ElauL::-moz-range-thumb{background-color:#000;border:none;border-radius:50%;cursor:pointer;height:12px;width:12px}.style-module_PlayerRangeSpeed__ElauL::-ms-thumb{background-color:#000;border-radius:50%;cursor:pointer;height:12px;width:12px}.style-module_PlayerCheckbox__At22K{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#eee;border-radius:14px;height:14px;width:14px}.style-module_PlayerCheckbox__At22K:checked{background-image:radial-gradient(circle at center,#fff 34%,#00b2ff 0)}.style-module_PlayerQualityList__rvIel{display:flex;flex-direction:column;font-size:12pt;gap:4px;overflow-y:auto;padding-inline:10px}.style-module_PlayerSettingList__KEYZR:hover{background-color:#eee6}.style-module_seekLeft__9AAFX,.style-module_seekRight__RMywZ{animation:style-module_shaking__Hgx0x .2s;font-size:24pt;position:absolute;text-shadow:0 0 2px rgba(0,0,0,.3);top:50%;transform:translateY(-50%)}@keyframes style-module_shaking__Hgx0x{0%{transform:translateY(-50%) scale(1)}50%{transform:translateY(-50%) scale(2)}to{transform:translateY(-50%) scale(1)}}@media (max-width:460px){.style-module_PlayerDurationTime__uCgjW,.style-module_PlayerVolumeZone__7LHeR{display:none}.style-module_PlayerVolume__r7ll8{padding-right:0}.style-module_seekLeft__9AAFX,.style-module_seekRight__RMywZ{font-size:18pt}}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { HlsConfig } from 'hls.js';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
quality
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
interface VideoPlayerProps {
|
|
3
|
+
type VideoSourceQuality = {
|
|
4
|
+
src: string;
|
|
5
|
+
quality: number;
|
|
6
|
+
};
|
|
7
|
+
type VideoPlayerProps = {
|
|
10
8
|
title?: string;
|
|
11
|
-
|
|
12
|
-
source: string |
|
|
13
|
-
}
|
|
14
|
-
|
|
9
|
+
poster?: string;
|
|
10
|
+
source: string | VideoSourceQuality[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
declare function VideoPlayer({ title, poster, source }: VideoPlayerProps): react_jsx_runtime.JSX.Element;
|
|
15
14
|
|
|
16
15
|
export { VideoPlayer };
|
|
16
|
+
export type { VideoSourceQuality };
|