floating-player 1.0.0
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 +76 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +211 -0
- package/dist/index.mjs +184 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Floating Video Player
|
|
2
|
+
|
|
3
|
+
A draggable and resizable floating video player (Picture-in-Picture) component for React.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install floating-video-player
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependencies
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install react react-dom
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import React, { useState } from 'react';
|
|
21
|
+
import { FloatingVideoPlayer } from 'floating-video-player';
|
|
22
|
+
|
|
23
|
+
function App() {
|
|
24
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<button onClick={() => setIsOpen(true)}>Open Video</button>
|
|
29
|
+
|
|
30
|
+
<FloatingVideoPlayer
|
|
31
|
+
open={isOpen}
|
|
32
|
+
onClose={() => setIsOpen(false)}
|
|
33
|
+
content="https://example.com/video.mp4"
|
|
34
|
+
initialWidth={400}
|
|
35
|
+
aspectRatio={16 / 9}
|
|
36
|
+
showControls={true}
|
|
37
|
+
handleColor="#212121"
|
|
38
|
+
backgroundColor="#ffffff"
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default App;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Props
|
|
48
|
+
|
|
49
|
+
| Prop | Type | Default | Description |
|
|
50
|
+
|------|------|---------|-------------|
|
|
51
|
+
| `open` | `boolean` | - | Controls whether the player is visible |
|
|
52
|
+
| `onClose` | `() => void` | - | Callback when close button is clicked |
|
|
53
|
+
| `content` | `string \| null \| undefined` | - | Video URL source |
|
|
54
|
+
| `initialWidth` | `number` | `window.innerWidth / 3` | Initial width in pixels |
|
|
55
|
+
| `initialHeight` | `number` | Calculated from aspect ratio | Initial height in pixels |
|
|
56
|
+
| `initialPosition` | `{ x: number, y: number }` | Bottom-right | Initial position |
|
|
57
|
+
| `aspectRatio` | `number` | `16/9` | Video aspect ratio |
|
|
58
|
+
| `showControls` | `boolean` | `true` | Show drag handle and close button |
|
|
59
|
+
| `className` | `string` | `''` | Additional CSS class |
|
|
60
|
+
| `style` | `React.CSSProperties` | - | Additional inline styles |
|
|
61
|
+
| `handleColor` | `string` | `'#212121'` | Background color of drag handle |
|
|
62
|
+
| `backgroundColor` | `string` | `'#ffffff'` | Background color of container |
|
|
63
|
+
|
|
64
|
+
## Features
|
|
65
|
+
|
|
66
|
+
- Draggable via mouse and touch
|
|
67
|
+
- Resizable from bottom-right corner
|
|
68
|
+
- Maintains aspect ratio while resizing
|
|
69
|
+
- Mobile responsive
|
|
70
|
+
- Automatic boundary constraints
|
|
71
|
+
- Autoplay on open
|
|
72
|
+
- No external UI library dependencies
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface FloatingVideoPlayerProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
content: string | undefined | null;
|
|
7
|
+
showControls?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
handleColor?: string;
|
|
10
|
+
backgroundColor?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const FloatingVideoPlayer: React.FC<FloatingVideoPlayerProps>;
|
|
13
|
+
|
|
14
|
+
export { FloatingVideoPlayer, type FloatingVideoPlayerProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface FloatingVideoPlayerProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
content: string | undefined | null;
|
|
7
|
+
showControls?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
handleColor?: string;
|
|
10
|
+
backgroundColor?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const FloatingVideoPlayer: React.FC<FloatingVideoPlayerProps>;
|
|
13
|
+
|
|
14
|
+
export { FloatingVideoPlayer, type FloatingVideoPlayerProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
FloatingVideoPlayer: () => FloatingVideoPlayer_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/FloatingVideoPlayer.tsx
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
var FloatingVideoPlayer = ({
|
|
31
|
+
open,
|
|
32
|
+
onClose,
|
|
33
|
+
content,
|
|
34
|
+
showControls = true,
|
|
35
|
+
className = "",
|
|
36
|
+
handleColor = "#212121",
|
|
37
|
+
backgroundColor = "#ffffff"
|
|
38
|
+
}) => {
|
|
39
|
+
const [pos, setPos] = (0, import_react.useState)({ x: 0, y: 0 });
|
|
40
|
+
const [size, setSize] = (0, import_react.useState)({ w: 480, h: 270 });
|
|
41
|
+
const isDragging = (0, import_react.useRef)(false);
|
|
42
|
+
const isResizing = (0, import_react.useRef)(false);
|
|
43
|
+
const dragOffset = (0, import_react.useRef)({ x: 0, y: 0 });
|
|
44
|
+
const startSize = (0, import_react.useRef)({ w: 0, h: 0 });
|
|
45
|
+
const startPos = (0, import_react.useRef)({ x: 0, y: 0 });
|
|
46
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
47
|
+
const videoRef = (0, import_react.useRef)(null);
|
|
48
|
+
(0, import_react.useEffect)(() => {
|
|
49
|
+
if (open) {
|
|
50
|
+
const w = Math.min(window.innerWidth * 0.4, 480);
|
|
51
|
+
const h = 270;
|
|
52
|
+
setSize({ w, h });
|
|
53
|
+
setPos({ x: window.innerWidth - w - 10, y: window.innerHeight - h - 10 });
|
|
54
|
+
}
|
|
55
|
+
}, [open]);
|
|
56
|
+
(0, import_react.useEffect)(() => {
|
|
57
|
+
const onMouseMove = (e) => {
|
|
58
|
+
if (isDragging.current) {
|
|
59
|
+
let newX = e.clientX - dragOffset.current.x;
|
|
60
|
+
let newY = e.clientY - dragOffset.current.y;
|
|
61
|
+
newX = Math.max(0, Math.min(window.innerWidth - size.w, newX));
|
|
62
|
+
newY = Math.max(0, Math.min(window.innerHeight - size.h, newY));
|
|
63
|
+
setPos({ x: newX, y: newY });
|
|
64
|
+
}
|
|
65
|
+
if (isResizing.current) {
|
|
66
|
+
const deltaX = e.clientX - startPos.current.x;
|
|
67
|
+
const deltaY = e.clientY - startPos.current.y;
|
|
68
|
+
const newW = Math.max(200, Math.min(startSize.current.w + deltaX, window.innerWidth));
|
|
69
|
+
const newH = Math.max(150, startSize.current.h + deltaY);
|
|
70
|
+
setSize({ w: newW, h: newH });
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const onMouseUp = () => {
|
|
74
|
+
isDragging.current = false;
|
|
75
|
+
isResizing.current = false;
|
|
76
|
+
document.body.style.cursor = "default";
|
|
77
|
+
document.body.style.userSelect = "auto";
|
|
78
|
+
};
|
|
79
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
80
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
81
|
+
return () => {
|
|
82
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
83
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
84
|
+
};
|
|
85
|
+
}, [size]);
|
|
86
|
+
const onDragStart = (e) => {
|
|
87
|
+
if (e.target.classList.contains("resize-handle")) return;
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
isDragging.current = true;
|
|
90
|
+
document.body.style.cursor = "grabbing";
|
|
91
|
+
document.body.style.userSelect = "none";
|
|
92
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
93
|
+
if (rect) {
|
|
94
|
+
dragOffset.current = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const onResizeStart = (e) => {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
isResizing.current = true;
|
|
101
|
+
document.body.style.cursor = "nwse-resize";
|
|
102
|
+
document.body.style.userSelect = "none";
|
|
103
|
+
startPos.current = { x: e.clientX, y: e.clientY };
|
|
104
|
+
startSize.current = { w: size.w, h: size.h };
|
|
105
|
+
};
|
|
106
|
+
(0, import_react.useEffect)(() => {
|
|
107
|
+
if (open && videoRef.current) {
|
|
108
|
+
videoRef.current.play().catch(() => {
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}, [open]);
|
|
112
|
+
if (!open || !content) return null;
|
|
113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
ref: containerRef,
|
|
117
|
+
className,
|
|
118
|
+
style: {
|
|
119
|
+
position: "fixed",
|
|
120
|
+
zIndex: 999999,
|
|
121
|
+
borderRadius: "8px",
|
|
122
|
+
overflow: "hidden",
|
|
123
|
+
display: "flex",
|
|
124
|
+
flexDirection: "column",
|
|
125
|
+
width: size.w,
|
|
126
|
+
height: size.h,
|
|
127
|
+
left: pos.x,
|
|
128
|
+
top: pos.y,
|
|
129
|
+
backgroundColor,
|
|
130
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.3)"
|
|
131
|
+
},
|
|
132
|
+
children: [
|
|
133
|
+
showControls && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
134
|
+
"div",
|
|
135
|
+
{
|
|
136
|
+
onMouseDown: onDragStart,
|
|
137
|
+
style: {
|
|
138
|
+
cursor: "grab",
|
|
139
|
+
display: "flex",
|
|
140
|
+
justifyContent: "space-between",
|
|
141
|
+
alignItems: "center",
|
|
142
|
+
backgroundColor: handleColor,
|
|
143
|
+
color: "#ffffff",
|
|
144
|
+
padding: "8px 12px",
|
|
145
|
+
userSelect: "none"
|
|
146
|
+
},
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "12px", opacity: 0.8 }, children: "\u22EE\u22EE Drag" }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
150
|
+
"button",
|
|
151
|
+
{
|
|
152
|
+
onClick: onClose,
|
|
153
|
+
style: {
|
|
154
|
+
background: "rgba(255,255,255,0.2)",
|
|
155
|
+
border: "none",
|
|
156
|
+
color: "#fff",
|
|
157
|
+
cursor: "pointer",
|
|
158
|
+
padding: "4px 8px",
|
|
159
|
+
borderRadius: "4px",
|
|
160
|
+
fontSize: "12px"
|
|
161
|
+
},
|
|
162
|
+
children: "\u2715"
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, backgroundColor: "#000", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
169
|
+
"video",
|
|
170
|
+
{
|
|
171
|
+
ref: videoRef,
|
|
172
|
+
style: { width: "100%", height: "100%", objectFit: "contain", display: "block" },
|
|
173
|
+
controls: true,
|
|
174
|
+
preload: "auto",
|
|
175
|
+
playsInline: true,
|
|
176
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("source", { src: content, type: "video/mp4" })
|
|
177
|
+
}
|
|
178
|
+
) }),
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
className: "resize-handle",
|
|
183
|
+
onMouseDown: onResizeStart,
|
|
184
|
+
style: {
|
|
185
|
+
position: "absolute",
|
|
186
|
+
right: 0,
|
|
187
|
+
bottom: 0,
|
|
188
|
+
width: "20px",
|
|
189
|
+
height: "20px",
|
|
190
|
+
cursor: "nwse-resize",
|
|
191
|
+
backgroundColor: "rgba(255,255,255,0.3)",
|
|
192
|
+
borderTopLeftRadius: "4px",
|
|
193
|
+
display: "flex",
|
|
194
|
+
alignItems: "center",
|
|
195
|
+
justifyContent: "center",
|
|
196
|
+
color: "#333",
|
|
197
|
+
fontSize: "12px",
|
|
198
|
+
fontWeight: "bold"
|
|
199
|
+
},
|
|
200
|
+
children: "\u2921"
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
var FloatingVideoPlayer_default = FloatingVideoPlayer;
|
|
208
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
209
|
+
0 && (module.exports = {
|
|
210
|
+
FloatingVideoPlayer
|
|
211
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// src/FloatingVideoPlayer.tsx
|
|
2
|
+
import { useState, useRef, useEffect } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var FloatingVideoPlayer = ({
|
|
5
|
+
open,
|
|
6
|
+
onClose,
|
|
7
|
+
content,
|
|
8
|
+
showControls = true,
|
|
9
|
+
className = "",
|
|
10
|
+
handleColor = "#212121",
|
|
11
|
+
backgroundColor = "#ffffff"
|
|
12
|
+
}) => {
|
|
13
|
+
const [pos, setPos] = useState({ x: 0, y: 0 });
|
|
14
|
+
const [size, setSize] = useState({ w: 480, h: 270 });
|
|
15
|
+
const isDragging = useRef(false);
|
|
16
|
+
const isResizing = useRef(false);
|
|
17
|
+
const dragOffset = useRef({ x: 0, y: 0 });
|
|
18
|
+
const startSize = useRef({ w: 0, h: 0 });
|
|
19
|
+
const startPos = useRef({ x: 0, y: 0 });
|
|
20
|
+
const containerRef = useRef(null);
|
|
21
|
+
const videoRef = useRef(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (open) {
|
|
24
|
+
const w = Math.min(window.innerWidth * 0.4, 480);
|
|
25
|
+
const h = 270;
|
|
26
|
+
setSize({ w, h });
|
|
27
|
+
setPos({ x: window.innerWidth - w - 10, y: window.innerHeight - h - 10 });
|
|
28
|
+
}
|
|
29
|
+
}, [open]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const onMouseMove = (e) => {
|
|
32
|
+
if (isDragging.current) {
|
|
33
|
+
let newX = e.clientX - dragOffset.current.x;
|
|
34
|
+
let newY = e.clientY - dragOffset.current.y;
|
|
35
|
+
newX = Math.max(0, Math.min(window.innerWidth - size.w, newX));
|
|
36
|
+
newY = Math.max(0, Math.min(window.innerHeight - size.h, newY));
|
|
37
|
+
setPos({ x: newX, y: newY });
|
|
38
|
+
}
|
|
39
|
+
if (isResizing.current) {
|
|
40
|
+
const deltaX = e.clientX - startPos.current.x;
|
|
41
|
+
const deltaY = e.clientY - startPos.current.y;
|
|
42
|
+
const newW = Math.max(200, Math.min(startSize.current.w + deltaX, window.innerWidth));
|
|
43
|
+
const newH = Math.max(150, startSize.current.h + deltaY);
|
|
44
|
+
setSize({ w: newW, h: newH });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const onMouseUp = () => {
|
|
48
|
+
isDragging.current = false;
|
|
49
|
+
isResizing.current = false;
|
|
50
|
+
document.body.style.cursor = "default";
|
|
51
|
+
document.body.style.userSelect = "auto";
|
|
52
|
+
};
|
|
53
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
54
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
55
|
+
return () => {
|
|
56
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
57
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
58
|
+
};
|
|
59
|
+
}, [size]);
|
|
60
|
+
const onDragStart = (e) => {
|
|
61
|
+
if (e.target.classList.contains("resize-handle")) return;
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
isDragging.current = true;
|
|
64
|
+
document.body.style.cursor = "grabbing";
|
|
65
|
+
document.body.style.userSelect = "none";
|
|
66
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
67
|
+
if (rect) {
|
|
68
|
+
dragOffset.current = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const onResizeStart = (e) => {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
isResizing.current = true;
|
|
75
|
+
document.body.style.cursor = "nwse-resize";
|
|
76
|
+
document.body.style.userSelect = "none";
|
|
77
|
+
startPos.current = { x: e.clientX, y: e.clientY };
|
|
78
|
+
startSize.current = { w: size.w, h: size.h };
|
|
79
|
+
};
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (open && videoRef.current) {
|
|
82
|
+
videoRef.current.play().catch(() => {
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}, [open]);
|
|
86
|
+
if (!open || !content) return null;
|
|
87
|
+
return /* @__PURE__ */ jsxs(
|
|
88
|
+
"div",
|
|
89
|
+
{
|
|
90
|
+
ref: containerRef,
|
|
91
|
+
className,
|
|
92
|
+
style: {
|
|
93
|
+
position: "fixed",
|
|
94
|
+
zIndex: 999999,
|
|
95
|
+
borderRadius: "8px",
|
|
96
|
+
overflow: "hidden",
|
|
97
|
+
display: "flex",
|
|
98
|
+
flexDirection: "column",
|
|
99
|
+
width: size.w,
|
|
100
|
+
height: size.h,
|
|
101
|
+
left: pos.x,
|
|
102
|
+
top: pos.y,
|
|
103
|
+
backgroundColor,
|
|
104
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.3)"
|
|
105
|
+
},
|
|
106
|
+
children: [
|
|
107
|
+
showControls && /* @__PURE__ */ jsxs(
|
|
108
|
+
"div",
|
|
109
|
+
{
|
|
110
|
+
onMouseDown: onDragStart,
|
|
111
|
+
style: {
|
|
112
|
+
cursor: "grab",
|
|
113
|
+
display: "flex",
|
|
114
|
+
justifyContent: "space-between",
|
|
115
|
+
alignItems: "center",
|
|
116
|
+
backgroundColor: handleColor,
|
|
117
|
+
color: "#ffffff",
|
|
118
|
+
padding: "8px 12px",
|
|
119
|
+
userSelect: "none"
|
|
120
|
+
},
|
|
121
|
+
children: [
|
|
122
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "12px", opacity: 0.8 }, children: "\u22EE\u22EE Drag" }),
|
|
123
|
+
/* @__PURE__ */ jsx(
|
|
124
|
+
"button",
|
|
125
|
+
{
|
|
126
|
+
onClick: onClose,
|
|
127
|
+
style: {
|
|
128
|
+
background: "rgba(255,255,255,0.2)",
|
|
129
|
+
border: "none",
|
|
130
|
+
color: "#fff",
|
|
131
|
+
cursor: "pointer",
|
|
132
|
+
padding: "4px 8px",
|
|
133
|
+
borderRadius: "4px",
|
|
134
|
+
fontSize: "12px"
|
|
135
|
+
},
|
|
136
|
+
children: "\u2715"
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, backgroundColor: "#000", position: "relative" }, children: /* @__PURE__ */ jsx(
|
|
143
|
+
"video",
|
|
144
|
+
{
|
|
145
|
+
ref: videoRef,
|
|
146
|
+
style: { width: "100%", height: "100%", objectFit: "contain", display: "block" },
|
|
147
|
+
controls: true,
|
|
148
|
+
preload: "auto",
|
|
149
|
+
playsInline: true,
|
|
150
|
+
children: /* @__PURE__ */ jsx("source", { src: content, type: "video/mp4" })
|
|
151
|
+
}
|
|
152
|
+
) }),
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: "resize-handle",
|
|
157
|
+
onMouseDown: onResizeStart,
|
|
158
|
+
style: {
|
|
159
|
+
position: "absolute",
|
|
160
|
+
right: 0,
|
|
161
|
+
bottom: 0,
|
|
162
|
+
width: "20px",
|
|
163
|
+
height: "20px",
|
|
164
|
+
cursor: "nwse-resize",
|
|
165
|
+
backgroundColor: "rgba(255,255,255,0.3)",
|
|
166
|
+
borderTopLeftRadius: "4px",
|
|
167
|
+
display: "flex",
|
|
168
|
+
alignItems: "center",
|
|
169
|
+
justifyContent: "center",
|
|
170
|
+
color: "#333",
|
|
171
|
+
fontSize: "12px",
|
|
172
|
+
fontWeight: "bold"
|
|
173
|
+
},
|
|
174
|
+
children: "\u2921"
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
var FloatingVideoPlayer_default = FloatingVideoPlayer;
|
|
182
|
+
export {
|
|
183
|
+
FloatingVideoPlayer_default as FloatingVideoPlayer
|
|
184
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "floating-player",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A draggable and resizable floating video player component for React",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.es.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --external react react-dom",
|
|
13
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": ">=16.8.0",
|
|
18
|
+
"react-dom": ">=16.8.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/react": "^18.2.0",
|
|
22
|
+
"@types/react-dom": "^18.2.0",
|
|
23
|
+
"react": "^18.2.0",
|
|
24
|
+
"react-dom": "^18.2.0",
|
|
25
|
+
"tsup": "^8.0.0",
|
|
26
|
+
"typescript": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"react",
|
|
30
|
+
"video",
|
|
31
|
+
"player",
|
|
32
|
+
"floating",
|
|
33
|
+
"pip",
|
|
34
|
+
"picture-in-picture",
|
|
35
|
+
"draggable",
|
|
36
|
+
"resizable"
|
|
37
|
+
],
|
|
38
|
+
"author": "Your Name <your.email@example.com>",
|
|
39
|
+
"license": "MIT"
|
|
40
|
+
}
|