@yumyum-player/ui 0.1.3
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 +50 -0
- package/README.ru.md +50 -0
- package/dist/YumYumPlayerView.d.ts +60 -0
- package/dist/YumYumPlayerView.js +538 -0
- package/dist/YumYumPlayerView.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
**English** · [Русский](./README.ru.md)
|
|
2
|
+
|
|
3
|
+
# @yumyum-player/ui
|
|
4
|
+
|
|
5
|
+
A reusable **React player shell** for [Yum-yum Player](../player-sdk) —
|
|
6
|
+
`<YumYumPlayerView>` — with YouTube-grade controls: timeline scrubber, volume,
|
|
7
|
+
playback speed, autoplay/loop, Picture-in-Picture, fullscreen and hotkeys. Also
|
|
8
|
+
exports small UI primitives (`Button`, `Slider`, `Badge`, `Spinner`, `Input`,
|
|
9
|
+
`Select`).
|
|
10
|
+
|
|
11
|
+
The view is decoupled from the engine: you pass a `createPlayer(canvas)` factory
|
|
12
|
+
that returns any object implementing the `PlayerHandle` interface — the core's
|
|
13
|
+
`YumYumPlayer` satisfies it structurally.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @yumyum-player/ui @yumyum-player/core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`react` and `react-dom` (18 or 19) are peer dependencies.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { YumYumPlayerView } from '@yumyum-player/ui';
|
|
27
|
+
import { YumYumPlayer } from '@yumyum-player/core';
|
|
28
|
+
|
|
29
|
+
export function Player() {
|
|
30
|
+
return (
|
|
31
|
+
<YumYumPlayerView
|
|
32
|
+
createPlayer={async (canvas) => {
|
|
33
|
+
const player = new YumYumPlayer({ canvas });
|
|
34
|
+
await player.load('https://example.com/stream.m3u8');
|
|
35
|
+
return { player, isLive: false };
|
|
36
|
+
}}
|
|
37
|
+
// optional:
|
|
38
|
+
// accentColor="#00ff66"
|
|
39
|
+
// playbackRate={1}
|
|
40
|
+
// controls={{ pip: true, fullscreen: true }}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Exported types: `YumYumPlayerViewProps`, `PlayerHandle`, `PlayerControlKey`.
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT — see the repository [LICENSE](../../LICENSE).
|
package/README.ru.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[English](./README.md) · **Русский**
|
|
2
|
+
|
|
3
|
+
# @yumyum-player/ui
|
|
4
|
+
|
|
5
|
+
Переиспользуемая **React-обвязка плеера** для [Yum-yum Player](../player-sdk) —
|
|
6
|
+
`<YumYumPlayerView>` — с контролами уровня YouTube: таймлайн-скраббер, громкость,
|
|
7
|
+
скорость, автоплей/повтор, Picture-in-Picture, полноэкранный режим и хоткеи.
|
|
8
|
+
Также экспортирует небольшие UI-примитивы (`Button`, `Slider`, `Badge`,
|
|
9
|
+
`Spinner`, `Input`, `Select`).
|
|
10
|
+
|
|
11
|
+
Вью развязана с движком: вы передаёте фабрику `createPlayer(canvas)`, которая
|
|
12
|
+
возвращает любой объект, реализующий интерфейс `PlayerHandle` — `YumYumPlayer` из
|
|
13
|
+
ядра удовлетворяет ему структурно.
|
|
14
|
+
|
|
15
|
+
## Установка
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @yumyum-player/ui @yumyum-player/core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`react` и `react-dom` (18 или 19) — peer-зависимости.
|
|
22
|
+
|
|
23
|
+
## Использование
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { YumYumPlayerView } from '@yumyum-player/ui';
|
|
27
|
+
import { YumYumPlayer } from '@yumyum-player/core';
|
|
28
|
+
|
|
29
|
+
export function Player() {
|
|
30
|
+
return (
|
|
31
|
+
<YumYumPlayerView
|
|
32
|
+
createPlayer={async (canvas) => {
|
|
33
|
+
const player = new YumYumPlayer({ canvas });
|
|
34
|
+
await player.load('https://example.com/stream.m3u8');
|
|
35
|
+
return { player, isLive: false };
|
|
36
|
+
}}
|
|
37
|
+
// опционально:
|
|
38
|
+
// accentColor="#00ff66"
|
|
39
|
+
// playbackRate={1}
|
|
40
|
+
// controls={{ pip: true, fullscreen: true }}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Экспортируемые типы: `YumYumPlayerViewProps`, `PlayerHandle`, `PlayerControlKey`.
|
|
47
|
+
|
|
48
|
+
## Лицензия
|
|
49
|
+
|
|
50
|
+
MIT — см. [LICENSE](../../LICENSE) репозитория.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal structural contract of the player this view drives. The real
|
|
4
|
+
* `YumYumPlayer` from `@yumyum-player/core` satisfies it structurally, so the
|
|
5
|
+
* UI package needs no build-time dependency on core.
|
|
6
|
+
*/
|
|
7
|
+
export interface PlayerHandle {
|
|
8
|
+
play(): Promise<void>;
|
|
9
|
+
pause(): void;
|
|
10
|
+
seek(timeSeconds: number): void;
|
|
11
|
+
setVolume(volume: number): void;
|
|
12
|
+
mute(isMuted: boolean): void;
|
|
13
|
+
setPlaybackRate(rate: number): void;
|
|
14
|
+
getPlaybackRate(): number;
|
|
15
|
+
getCurrentTime(): number;
|
|
16
|
+
getDuration(): number;
|
|
17
|
+
getTelemetry(): {
|
|
18
|
+
currentPTS: number;
|
|
19
|
+
duration: number;
|
|
20
|
+
bufferedEnd: number;
|
|
21
|
+
playbackState: string;
|
|
22
|
+
playbackRate: number;
|
|
23
|
+
renderedFrames: number;
|
|
24
|
+
activeCodec: string;
|
|
25
|
+
queueLength: number;
|
|
26
|
+
};
|
|
27
|
+
on(event: string, callback: (...args: unknown[]) => void): void;
|
|
28
|
+
off(event: string, callback: (...args: unknown[]) => void): void;
|
|
29
|
+
destroy(): void;
|
|
30
|
+
}
|
|
31
|
+
export type PlayerControlKey = 'play' | 'volume' | 'timeline' | 'time' | 'speed' | 'settings' | 'pip' | 'fullscreen';
|
|
32
|
+
export interface YumYumPlayerViewProps {
|
|
33
|
+
/**
|
|
34
|
+
* Construct + load a player against the given canvas. Resolves once the
|
|
35
|
+
* stream is loaded; `isLive` disables seeking and shows a LIVE badge.
|
|
36
|
+
*/
|
|
37
|
+
createPlayer: (canvas: HTMLCanvasElement) => Promise<{
|
|
38
|
+
player: PlayerHandle;
|
|
39
|
+
isLive: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
/** Accent color for the progress bar, handle and active controls. */
|
|
42
|
+
accentColor?: string;
|
|
43
|
+
/** Controlled playback speed: when this prop changes it is applied live. */
|
|
44
|
+
playbackRate?: number;
|
|
45
|
+
/** Toggle visibility of individual controls. Omitted keys default to visible. */
|
|
46
|
+
controls?: Partial<Record<PlayerControlKey, boolean>>;
|
|
47
|
+
/** Milliseconds of mouse inactivity before controls auto-hide while playing. */
|
|
48
|
+
autoHideDelay?: number;
|
|
49
|
+
/** localStorage namespace for persisted volume/muted/rate/autoplay/loop. */
|
|
50
|
+
persistKeyPrefix?: string;
|
|
51
|
+
lang?: 'ru' | 'en';
|
|
52
|
+
className?: string;
|
|
53
|
+
overlayTopLeft?: React.ReactNode;
|
|
54
|
+
overlayTopRight?: React.ReactNode;
|
|
55
|
+
badges?: {
|
|
56
|
+
label: string;
|
|
57
|
+
variant?: 'rec' | 'primary' | 'warning' | 'neutral';
|
|
58
|
+
}[];
|
|
59
|
+
}
|
|
60
|
+
export declare const YumYumPlayerView: React.FC<YumYumPlayerViewProps>;
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { Badge, Button, Slider, Spinner } from './index.js';
|
|
5
|
+
const PLAYBACK_RATES = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
6
|
+
const STRINGS = {
|
|
7
|
+
ru: { speed: 'Скорость', normal: 'Обычная', autoplay: 'Автовоспроизведение', loop: 'Повтор', live: 'В ЭФИРЕ', settings: 'Настройки', on: 'Вкл', off: 'Выкл' },
|
|
8
|
+
en: { speed: 'Speed', normal: 'Normal', autoplay: 'Autoplay', loop: 'Loop', live: 'LIVE', settings: 'Settings', on: 'On', off: 'Off' },
|
|
9
|
+
};
|
|
10
|
+
function formatTime(seconds) {
|
|
11
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
12
|
+
return '0:00';
|
|
13
|
+
const s = Math.floor(seconds % 60);
|
|
14
|
+
const m = Math.floor((seconds / 60) % 60);
|
|
15
|
+
const h = Math.floor(seconds / 3600);
|
|
16
|
+
const ss = s.toString().padStart(2, '0');
|
|
17
|
+
if (h > 0)
|
|
18
|
+
return `${h}:${m.toString().padStart(2, '0')}:${ss}`;
|
|
19
|
+
return `${m}:${ss}`;
|
|
20
|
+
}
|
|
21
|
+
// ── localStorage helpers (SSR/quota safe) ──────────────────────────
|
|
22
|
+
function readStore(key, fallback) {
|
|
23
|
+
if (typeof window === 'undefined')
|
|
24
|
+
return fallback;
|
|
25
|
+
try {
|
|
26
|
+
const raw = window.localStorage.getItem(key);
|
|
27
|
+
return raw === null ? fallback : JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function writeStore(key, value) {
|
|
34
|
+
if (typeof window === 'undefined')
|
|
35
|
+
return;
|
|
36
|
+
try {
|
|
37
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
/* ignore quota / private mode errors */
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// ── Self-contained stylesheet (injected once) ──────────────────────
|
|
44
|
+
const STYLE_ID = 'yyv-styles';
|
|
45
|
+
const STYLE = `
|
|
46
|
+
.yyv-root{position:relative;width:100%;height:100%;background:#000;overflow:hidden;user-select:none;outline:none;font-family:ui-sans-serif,system-ui,sans-serif}
|
|
47
|
+
.yyv-root.yyv-nocursor{cursor:none}
|
|
48
|
+
.yyv-canvas{position:relative;z-index:1;width:100%;height:100%;object-fit:contain;display:block;background:#000}
|
|
49
|
+
/* PiP mirror: a REAL, full-size <video> painted *behind* the canvas. It must
|
|
50
|
+
not be 1px / opacity:0 — browsers suspend frame production for effectively
|
|
51
|
+
invisible videos, so requestPictureInPicture() then resolves but opens an
|
|
52
|
+
empty window (silent no-op). The opaque canvas on top (z-index:1) is what
|
|
53
|
+
the user actually sees; this mirror is fully occluded but still painted. */
|
|
54
|
+
.yyv-pipvideo{position:absolute;inset:0;z-index:0;width:100%;height:100%;object-fit:contain;background:#000;pointer-events:none}
|
|
55
|
+
.yyv-center{position:absolute;inset:0;margin:auto;height:64px;width:64px;border-radius:50%;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;z-index:10;transition:background .15s}
|
|
56
|
+
.yyv-center:hover{background:rgba(0,0,0,.8)}
|
|
57
|
+
.yyv-spin{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:10}
|
|
58
|
+
.yyv-spin svg{animation:yyv-rot 1s linear infinite;height:48px;width:48px}
|
|
59
|
+
@keyframes yyv-rot{to{transform:rotate(360deg)}}
|
|
60
|
+
.yyv-error{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#f87171;font:13px ui-monospace,monospace;z-index:20;pointer-events:none}
|
|
61
|
+
.yyv-overlay-tl{position:absolute;top:8px;left:8px;z-index:50;display:flex;gap:6px;pointer-events:auto}
|
|
62
|
+
.yyv-overlay-tr{position:absolute;top:8px;right:8px;z-index:50;display:flex;gap:6px;pointer-events:auto}
|
|
63
|
+
.yyv-bar{position:absolute;left:0;right:0;bottom:0;z-index:30;padding:36px 12px 10px;background:linear-gradient(to top,rgba(0,0,0,.9),rgba(0,0,0,.45) 55%,transparent);transition:opacity .2s;color:#fff}
|
|
64
|
+
.yyv-bar.yyv-hidden{opacity:0;pointer-events:none}
|
|
65
|
+
.yyv-row{display:flex;align-items:center;gap:14px}
|
|
66
|
+
.yyv-btn{background:none;border:none;color:#fff;cursor:pointer;padding:0;margin:0;display:flex;align-items:center;justify-content:center;opacity:.92;transition:opacity .15s,transform .15s;line-height:0}
|
|
67
|
+
.yyv-btn:hover{opacity:1}
|
|
68
|
+
.yyv-spacer{flex:1}
|
|
69
|
+
.yyv-time{font:600 12px/1 ui-monospace,monospace;color:rgba(255,255,255,.92);white-space:nowrap}
|
|
70
|
+
.yyv-tlrow{margin-bottom:6px;display:flex;align-items:center;min-height:18px}
|
|
71
|
+
.yyv-tlwrap{position:relative;width:100%;padding:7px 0;cursor:pointer;touch-action:none}
|
|
72
|
+
.yyv-tl{position:relative;height:5px;width:100%;background:rgba(255,255,255,.3);border-radius:999px;transition:height .1s}
|
|
73
|
+
.yyv-tlwrap:hover .yyv-tl{height:7px}
|
|
74
|
+
.yyv-tlbuf{position:absolute;left:0;top:0;height:100%;background:rgba(255,255,255,.45);border-radius:999px}
|
|
75
|
+
.yyv-tlplayed{position:absolute;left:0;top:0;height:100%;border-radius:999px}
|
|
76
|
+
.yyv-tlhandle{position:absolute;top:50%;height:14px;width:14px;border-radius:50%;box-shadow:0 0 3px rgba(0,0,0,.7);opacity:0;transform:translate(-50%,-50%);transition:opacity .12s}
|
|
77
|
+
.yyv-tlwrap:hover .yyv-tlhandle,.yyv-tlwrap.yyv-scrub .yyv-tlhandle{opacity:1}
|
|
78
|
+
.yyv-tip{position:absolute;bottom:20px;transform:translateX(-50%);background:rgba(0,0,0,.9);color:#fff;font:11px/1 ui-monospace,monospace;padding:3px 6px;border-radius:4px;pointer-events:none;white-space:nowrap}
|
|
79
|
+
.yyv-live{display:flex;align-items:center;gap:6px;font:700 11px/1 ui-monospace,monospace;color:#ff3b30;letter-spacing:.12em}
|
|
80
|
+
.yyv-livedot{height:8px;width:8px;border-radius:50%;background:#ff3b30;animation:yyv-pulse 1.4s infinite}
|
|
81
|
+
@keyframes yyv-pulse{0%,100%{opacity:1}50%{opacity:.3}}
|
|
82
|
+
.yyv-vol{display:flex;align-items:center;gap:8px}
|
|
83
|
+
.yyv-volrange{width:0;opacity:0;height:4px;cursor:pointer;transition:width .2s,opacity .2s;vertical-align:middle}
|
|
84
|
+
.yyv-vol:hover .yyv-volrange,.yyv-volrange:focus{width:74px;opacity:1}
|
|
85
|
+
.yyv-menu{position:absolute;bottom:42px;right:0;width:190px;max-height:60vh;overflow-y:auto;background:rgba(22,22,22,.98);border:1px solid rgba(255,255,255,.15);border-radius:8px;color:#fff;font:12px/1.2 ui-sans-serif,system-ui,sans-serif;padding:4px 0;box-shadow:0 10px 30px rgba(0,0,0,.55);z-index:40}
|
|
86
|
+
.yyv-mi{width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 12px;background:none;border:none;color:#fff;cursor:pointer;text-align:left;font:inherit}
|
|
87
|
+
.yyv-mi:hover{background:rgba(255,255,255,.1)}
|
|
88
|
+
.yyv-sep{margin:4px 0;border-top:1px solid rgba(255,255,255,.1)}
|
|
89
|
+
.yyv-mlabel{padding:5px 12px;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:rgba(255,255,255,.5)}
|
|
90
|
+
`;
|
|
91
|
+
function ensureStyles() {
|
|
92
|
+
if (typeof document === 'undefined' || document.getElementById(STYLE_ID))
|
|
93
|
+
return;
|
|
94
|
+
const el = document.createElement('style');
|
|
95
|
+
el.id = STYLE_ID;
|
|
96
|
+
el.textContent = STYLE;
|
|
97
|
+
document.head.appendChild(el);
|
|
98
|
+
}
|
|
99
|
+
// ── Inline SVG icons ────────────────────────────────────────────────
|
|
100
|
+
const ic = { width: 22, height: 22, viewBox: '0 0 24 24', fill: 'currentColor' };
|
|
101
|
+
const PlayIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M8 5v14l11-7z" }) });
|
|
102
|
+
const PauseIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M6 5h4v14H6zm8 0h4v14h-4z" }) });
|
|
103
|
+
const VolumeHighIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zM14 3.2v2.1a7 7 0 0 1 0 13.4v2.1a9 9 0 0 0 0-17.6z" }) });
|
|
104
|
+
const VolumeMuteIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M3 10v4h4l5 5V5L7 10H3zm18.3-1.3-1.4-1.4L17 10.2 14.1 7.3l-1.4 1.4L15.6 12l-2.9 2.9 1.4 1.4L17 13.4l2.9 2.9 1.4-1.4L18.4 12z" }) });
|
|
105
|
+
const GearIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.488.488 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z" }) });
|
|
106
|
+
const PipIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M19 7h-8v6h8V7zm2-4H3a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zm0 16.01H3V4.98h18v14.03z" }) });
|
|
107
|
+
const FullscreenIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" }) });
|
|
108
|
+
const FullscreenExitIcon = () => _jsx("svg", { ...ic, children: _jsx("path", { d: "M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" }) });
|
|
109
|
+
const CheckIcon = () => _jsx("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z" }) });
|
|
110
|
+
// ── Timeline scrubber with buffered bar + hover tooltip ─────────────
|
|
111
|
+
const Timeline = ({ currentTime, duration, buffered, accent, onSeek, onScrubStart, onScrubEnd, onScrubMove }) => {
|
|
112
|
+
const ref = useRef(null);
|
|
113
|
+
const draggingRef = useRef(false); // synchronous guard (state lags for fast clicks)
|
|
114
|
+
const [dragging, setDragging] = useState(false);
|
|
115
|
+
const [hover, setHover] = useState(null);
|
|
116
|
+
const timeAt = (clientX) => {
|
|
117
|
+
const rect = ref.current.getBoundingClientRect();
|
|
118
|
+
const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
|
|
119
|
+
return pct * duration;
|
|
120
|
+
};
|
|
121
|
+
const handleDown = (e) => {
|
|
122
|
+
if (!ref.current || !Number.isFinite(duration) || duration <= 0)
|
|
123
|
+
return;
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
draggingRef.current = true;
|
|
126
|
+
setDragging(true);
|
|
127
|
+
try {
|
|
128
|
+
ref.current.setPointerCapture(e.pointerId);
|
|
129
|
+
}
|
|
130
|
+
catch { /* noop */ }
|
|
131
|
+
onScrubStart();
|
|
132
|
+
onScrubMove(timeAt(e.clientX));
|
|
133
|
+
};
|
|
134
|
+
const handleMove = (e) => {
|
|
135
|
+
if (!ref.current || !Number.isFinite(duration) || duration <= 0)
|
|
136
|
+
return;
|
|
137
|
+
const rect = ref.current.getBoundingClientRect();
|
|
138
|
+
const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
139
|
+
setHover({ x: pct * 100, t: pct * duration });
|
|
140
|
+
if (draggingRef.current)
|
|
141
|
+
onScrubMove(pct * duration);
|
|
142
|
+
};
|
|
143
|
+
const handleUp = (e) => {
|
|
144
|
+
if (!draggingRef.current || !ref.current)
|
|
145
|
+
return;
|
|
146
|
+
draggingRef.current = false;
|
|
147
|
+
setDragging(false);
|
|
148
|
+
try {
|
|
149
|
+
ref.current.releasePointerCapture(e.pointerId);
|
|
150
|
+
}
|
|
151
|
+
catch { /* noop */ }
|
|
152
|
+
onSeek(timeAt(e.clientX));
|
|
153
|
+
onScrubEnd();
|
|
154
|
+
};
|
|
155
|
+
const has = Number.isFinite(duration) && duration > 0;
|
|
156
|
+
const pct = has ? Math.min(100, (currentTime / duration) * 100) : 0;
|
|
157
|
+
const bufPct = has ? Math.min(100, (buffered / duration) * 100) : 0;
|
|
158
|
+
return (_jsxs("div", { ref: ref, className: `yyv-tlwrap${dragging ? ' yyv-scrub' : ''}`, onPointerDown: handleDown, onPointerMove: handleMove, onPointerUp: handleUp, onPointerLeave: () => setHover(null), children: [_jsxs("div", { className: "yyv-tl", children: [_jsx("div", { className: "yyv-tlbuf", style: { width: `${bufPct}%` } }), _jsx("div", { className: "yyv-tlplayed", style: { width: `${pct}%`, backgroundColor: accent } }), _jsx("div", { className: "yyv-tlhandle", style: { left: `${pct}%`, backgroundColor: accent } })] }), hover && has && (_jsx("div", { className: "yyv-tip", style: { left: `${hover.x}%` }, children: formatTime(hover.t) }))] }));
|
|
159
|
+
};
|
|
160
|
+
export const YumYumPlayerView = ({ createPlayer, accentColor = '#00FF66', playbackRate, controls, autoHideDelay = 3000, persistKeyPrefix = 'yumyum', lang = 'en', className = '', overlayTopLeft, overlayTopRight, badges, }) => {
|
|
161
|
+
const show = (k) => controls?.[k] !== false;
|
|
162
|
+
const t = STRINGS[lang];
|
|
163
|
+
const K = useCallback((name) => `${persistKeyPrefix}:${name}`, [persistKeyPrefix]);
|
|
164
|
+
const canvasRef = useRef(null);
|
|
165
|
+
const containerRef = useRef(null);
|
|
166
|
+
const pipVideoRef = useRef(null);
|
|
167
|
+
const playerRef = useRef(null);
|
|
168
|
+
const hideTimer = useRef(null);
|
|
169
|
+
const scrubbing = useRef(false);
|
|
170
|
+
const loopRef = useRef(false);
|
|
171
|
+
const hoveredRef = useRef(false);
|
|
172
|
+
const pipPreppedRef = useRef(false); // PiP <video> mirror is live and ready
|
|
173
|
+
const [volume, setVolume] = useState(() => readStore(`${persistKeyPrefix}:volume`, 0.8));
|
|
174
|
+
const [muted, setMuted] = useState(() => readStore(`${persistKeyPrefix}:muted`, true));
|
|
175
|
+
const [rate, setRate] = useState(() => playbackRate ?? readStore(`${persistKeyPrefix}:rate`, 1));
|
|
176
|
+
const [autoplay, setAutoplay] = useState(() => readStore(`${persistKeyPrefix}:autoplay`, false));
|
|
177
|
+
const [loop, setLoop] = useState(() => readStore(`${persistKeyPrefix}:loop`, false));
|
|
178
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
179
|
+
const [isLive, setIsLive] = useState(false);
|
|
180
|
+
const [isBuffering, setIsBuffering] = useState(false);
|
|
181
|
+
const [isReady, setIsReady] = useState(false);
|
|
182
|
+
const [hasError, setHasError] = useState(false);
|
|
183
|
+
const [currentTime, setCurrentTime] = useState(0);
|
|
184
|
+
const [duration, setDuration] = useState(0);
|
|
185
|
+
const [buffered, setBuffered] = useState(0);
|
|
186
|
+
const [scrubTime, setScrubTime] = useState(null);
|
|
187
|
+
const [controlsVisible, setControlsVisible] = useState(true);
|
|
188
|
+
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
189
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
190
|
+
const [pipSupported, setPipSupported] = useState(false);
|
|
191
|
+
loopRef.current = loop;
|
|
192
|
+
useEffect(() => { ensureStyles(); }, []);
|
|
193
|
+
// ── Player lifecycle ──────────────────────────────────────────────
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if (!canvasRef.current)
|
|
196
|
+
return;
|
|
197
|
+
setIsReady(false);
|
|
198
|
+
let mounted = true;
|
|
199
|
+
let poll = null;
|
|
200
|
+
let created = null;
|
|
201
|
+
let lastFrames = -1;
|
|
202
|
+
let stallTicks = 0;
|
|
203
|
+
const onEnded = () => {
|
|
204
|
+
if (!mounted)
|
|
205
|
+
return;
|
|
206
|
+
if (loopRef.current && created) {
|
|
207
|
+
created.seek(0);
|
|
208
|
+
created.play().catch(() => { });
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
setIsPlaying(false);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
(async () => {
|
|
215
|
+
try {
|
|
216
|
+
const { player, isLive: live } = await createPlayer(canvasRef.current);
|
|
217
|
+
if (!mounted) {
|
|
218
|
+
player.destroy();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
created = player;
|
|
222
|
+
playerRef.current = player;
|
|
223
|
+
setIsLive(live);
|
|
224
|
+
player.setVolume(muted ? 0 : volume);
|
|
225
|
+
player.mute(muted);
|
|
226
|
+
if (rate !== 1)
|
|
227
|
+
player.setPlaybackRate(rate);
|
|
228
|
+
player.on('ended', onEnded);
|
|
229
|
+
player.on('error', () => { if (mounted)
|
|
230
|
+
setHasError(true); });
|
|
231
|
+
if (mounted)
|
|
232
|
+
setIsReady(true);
|
|
233
|
+
if (live || autoplay) {
|
|
234
|
+
player.play().then(() => { if (mounted)
|
|
235
|
+
setIsPlaying(true); }).catch(() => { });
|
|
236
|
+
}
|
|
237
|
+
poll = setInterval(() => {
|
|
238
|
+
if (!mounted || !created)
|
|
239
|
+
return;
|
|
240
|
+
const tel = created.getTelemetry();
|
|
241
|
+
if (!scrubbing.current)
|
|
242
|
+
setCurrentTime(tel.currentPTS);
|
|
243
|
+
setDuration(tel.duration);
|
|
244
|
+
setBuffered(tel.bufferedEnd);
|
|
245
|
+
const playing = tel.playbackState === 'PLAYING';
|
|
246
|
+
setIsPlaying(playing);
|
|
247
|
+
// Stall = playing, queue drained, and no new frame since last tick.
|
|
248
|
+
// Require a few consecutive stalled ticks before showing the spinner
|
|
249
|
+
// so a brief gap (e.g. right after a seek) doesn't flash it, and clear
|
|
250
|
+
// it instantly the moment frames start flowing again.
|
|
251
|
+
const tickStalled = playing && tel.renderedFrames === lastFrames
|
|
252
|
+
&& tel.queueLength === 0 && tel.activeCodec !== 'mjpeg';
|
|
253
|
+
stallTicks = tickStalled ? stallTicks + 1 : 0;
|
|
254
|
+
setIsBuffering(stallTicks >= 3);
|
|
255
|
+
lastFrames = tel.renderedFrames;
|
|
256
|
+
// Eagerly mirror the canvas into the off-screen PiP <video> once frames
|
|
257
|
+
// exist, and keep it playing. This is essential: requestPictureInPicture()
|
|
258
|
+
// must run synchronously inside the click gesture, so the stream must be
|
|
259
|
+
// ready *before* the user clicks (awaiting play()/metadata in the handler
|
|
260
|
+
// consumes the gesture and the browser rejects it).
|
|
261
|
+
if (!pipPreppedRef.current && tel.renderedFrames > 0) {
|
|
262
|
+
const cv = canvasRef.current;
|
|
263
|
+
const vid = pipVideoRef.current;
|
|
264
|
+
if (cv && vid && typeof cv.captureStream === 'function') {
|
|
265
|
+
try {
|
|
266
|
+
const prev = vid.srcObject;
|
|
267
|
+
if (prev)
|
|
268
|
+
prev.getTracks().forEach((tr) => tr.stop());
|
|
269
|
+
vid.srcObject = cv.captureStream(30);
|
|
270
|
+
vid.play().catch(() => { });
|
|
271
|
+
pipPreppedRef.current = true;
|
|
272
|
+
}
|
|
273
|
+
catch { /* captureStream unsupported */ }
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}, 250);
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
if (mounted)
|
|
280
|
+
setHasError(true);
|
|
281
|
+
}
|
|
282
|
+
})();
|
|
283
|
+
return () => {
|
|
284
|
+
mounted = false;
|
|
285
|
+
pipPreppedRef.current = false;
|
|
286
|
+
if (poll)
|
|
287
|
+
clearInterval(poll);
|
|
288
|
+
if (created) {
|
|
289
|
+
created.off('ended', onEnded);
|
|
290
|
+
try {
|
|
291
|
+
created.destroy();
|
|
292
|
+
}
|
|
293
|
+
catch { /* noop */ }
|
|
294
|
+
}
|
|
295
|
+
playerRef.current = null;
|
|
296
|
+
};
|
|
297
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
298
|
+
}, [createPlayer]);
|
|
299
|
+
// ── Controlled playback rate: apply live when the prop changes ─────
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
if (playbackRate === undefined)
|
|
302
|
+
return;
|
|
303
|
+
setRate(playbackRate);
|
|
304
|
+
writeStore(K('rate'), playbackRate);
|
|
305
|
+
playerRef.current?.setPlaybackRate(playbackRate);
|
|
306
|
+
}, [playbackRate, K]);
|
|
307
|
+
// ── Fullscreen + PiP capability ───────────────────────────────────
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
const onFsChange = () => setIsFullscreen(document.fullscreenElement === containerRef.current);
|
|
310
|
+
document.addEventListener('fullscreenchange', onFsChange);
|
|
311
|
+
// PiP needs (a) a canvas we can mirror via captureStream and (b) a PiP API:
|
|
312
|
+
// the standard one (Chrome/Edge/Firefox) or WebKit's presentation-mode API
|
|
313
|
+
// (Safari, which doesn't expose document.pictureInPictureEnabled).
|
|
314
|
+
const canCapture = typeof HTMLCanvasElement !== 'undefined' && 'captureStream' in HTMLCanvasElement.prototype;
|
|
315
|
+
const standardPip = typeof document !== 'undefined' && document.pictureInPictureEnabled === true;
|
|
316
|
+
const webkitPip = typeof HTMLVideoElement !== 'undefined' &&
|
|
317
|
+
typeof HTMLVideoElement.prototype.webkitSetPresentationMode === 'function';
|
|
318
|
+
setPipSupported(canCapture && (standardPip || webkitPip));
|
|
319
|
+
return () => document.removeEventListener('fullscreenchange', onFsChange);
|
|
320
|
+
}, []);
|
|
321
|
+
// ── Control actions ───────────────────────────────────────────────
|
|
322
|
+
const togglePlay = useCallback(() => {
|
|
323
|
+
const p = playerRef.current;
|
|
324
|
+
if (!p || hasError)
|
|
325
|
+
return;
|
|
326
|
+
if (isPlaying) {
|
|
327
|
+
p.pause();
|
|
328
|
+
setIsPlaying(false);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
p.play().then(() => setIsPlaying(true)).catch(() => { });
|
|
332
|
+
}
|
|
333
|
+
}, [isPlaying, hasError]);
|
|
334
|
+
const applyVolume = useCallback((v) => {
|
|
335
|
+
const vol = Math.max(0, Math.min(1, v));
|
|
336
|
+
const isMute = vol === 0;
|
|
337
|
+
setVolume(vol);
|
|
338
|
+
setMuted(isMute);
|
|
339
|
+
writeStore(K('volume'), vol);
|
|
340
|
+
writeStore(K('muted'), isMute);
|
|
341
|
+
const p = playerRef.current;
|
|
342
|
+
if (p) {
|
|
343
|
+
p.mute(isMute);
|
|
344
|
+
p.setVolume(vol);
|
|
345
|
+
}
|
|
346
|
+
}, [K]);
|
|
347
|
+
const toggleMute = useCallback(() => {
|
|
348
|
+
const next = !muted;
|
|
349
|
+
setMuted(next);
|
|
350
|
+
writeStore(K('muted'), next);
|
|
351
|
+
const p = playerRef.current;
|
|
352
|
+
if (p) {
|
|
353
|
+
p.mute(next);
|
|
354
|
+
p.setVolume(next ? 0 : volume || 0.5);
|
|
355
|
+
}
|
|
356
|
+
if (!next && (volume || 0) === 0)
|
|
357
|
+
applyVolume(0.5);
|
|
358
|
+
}, [muted, volume, K, applyVolume]);
|
|
359
|
+
const applyRate = useCallback((r) => {
|
|
360
|
+
setRate(r);
|
|
361
|
+
writeStore(K('rate'), r);
|
|
362
|
+
playerRef.current?.setPlaybackRate(r);
|
|
363
|
+
}, [K]);
|
|
364
|
+
const relSeek = useCallback((delta) => {
|
|
365
|
+
const p = playerRef.current;
|
|
366
|
+
if (!p || isLive)
|
|
367
|
+
return;
|
|
368
|
+
const target = Math.max(0, Math.min(duration || Infinity, p.getCurrentTime() + delta));
|
|
369
|
+
p.seek(target);
|
|
370
|
+
setCurrentTime(target);
|
|
371
|
+
}, [isLive, duration]);
|
|
372
|
+
const toggleFullscreen = useCallback(() => {
|
|
373
|
+
const el = containerRef.current;
|
|
374
|
+
if (!el)
|
|
375
|
+
return;
|
|
376
|
+
if (document.fullscreenElement)
|
|
377
|
+
document.exitFullscreen().catch(() => { });
|
|
378
|
+
else
|
|
379
|
+
el.requestFullscreen().catch(() => { });
|
|
380
|
+
}, []);
|
|
381
|
+
const togglePip = useCallback(() => {
|
|
382
|
+
const canvas = canvasRef.current;
|
|
383
|
+
const video = pipVideoRef.current;
|
|
384
|
+
if (!video)
|
|
385
|
+
return;
|
|
386
|
+
// Already in PiP → leave it (standard API, then WebKit/Safari).
|
|
387
|
+
if (document.pictureInPictureElement === video) {
|
|
388
|
+
document.exitPictureInPicture().catch(() => { });
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (video.webkitPresentationMode === 'picture-in-picture') {
|
|
392
|
+
video.webkitSetPresentationMode?.('inline');
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
// Last-resort prep if the eager setup hasn't run yet (e.g. clicked very early).
|
|
396
|
+
if (!video.srcObject && canvas) {
|
|
397
|
+
const cv = canvas;
|
|
398
|
+
if (typeof cv.captureStream === 'function') {
|
|
399
|
+
try {
|
|
400
|
+
video.srcObject = cv.captureStream(30);
|
|
401
|
+
pipPreppedRef.current = true;
|
|
402
|
+
}
|
|
403
|
+
catch { /* noop */ }
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Keep the mirror playing so frames — and therefore metadata — start flowing.
|
|
407
|
+
video.play().catch(() => { });
|
|
408
|
+
const request = () => {
|
|
409
|
+
if (typeof video.requestPictureInPicture === 'function') {
|
|
410
|
+
video.requestPictureInPicture().catch((err) => {
|
|
411
|
+
// eslint-disable-next-line no-console
|
|
412
|
+
console.warn('[YumYumPlayerView] Picture-in-Picture unavailable:', err);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
else if (typeof video.webkitSetPresentationMode === 'function') {
|
|
416
|
+
// Safari: no standard API — use the WebKit presentation-mode fallback.
|
|
417
|
+
try {
|
|
418
|
+
video.webkitSetPresentationMode('picture-in-picture');
|
|
419
|
+
}
|
|
420
|
+
// eslint-disable-next-line no-console
|
|
421
|
+
catch (err) {
|
|
422
|
+
console.warn('[YumYumPlayerView] Picture-in-Picture unavailable:', err);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
// requestPictureInPicture() throws InvalidStateError if the <video> has no
|
|
427
|
+
// metadata yet (the captureStream was only just attached, or the user clicked
|
|
428
|
+
// before the eager prep ran). When that's the case, wait for the first frame's
|
|
429
|
+
// metadata and request then — Chrome keeps the click's transient activation
|
|
430
|
+
// alive for a few seconds, so the user gesture is still valid.
|
|
431
|
+
if (video.readyState >= 1 /* HAVE_METADATA */) {
|
|
432
|
+
request();
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
video.addEventListener('loadedmetadata', request, { once: true });
|
|
436
|
+
}
|
|
437
|
+
}, []);
|
|
438
|
+
// Exit PiP and release the captured MediaStream when the view unmounts.
|
|
439
|
+
useEffect(() => () => {
|
|
440
|
+
const video = pipVideoRef.current;
|
|
441
|
+
try {
|
|
442
|
+
if (video && document.pictureInPictureElement === video)
|
|
443
|
+
document.exitPictureInPicture().catch(() => { });
|
|
444
|
+
if (video?.webkitPresentationMode === 'picture-in-picture')
|
|
445
|
+
video.webkitSetPresentationMode?.('inline');
|
|
446
|
+
}
|
|
447
|
+
catch { /* noop */ }
|
|
448
|
+
const stream = video?.srcObject;
|
|
449
|
+
if (stream)
|
|
450
|
+
stream.getTracks().forEach((tr) => tr.stop());
|
|
451
|
+
if (video)
|
|
452
|
+
video.srcObject = null;
|
|
453
|
+
}, []);
|
|
454
|
+
// ── Auto-hide controls while playing ──────────────────────────────
|
|
455
|
+
const revealControls = useCallback(() => {
|
|
456
|
+
hoveredRef.current = true; // any mouse activity over the player arms hotkeys
|
|
457
|
+
setControlsVisible(true);
|
|
458
|
+
if (hideTimer.current)
|
|
459
|
+
clearTimeout(hideTimer.current);
|
|
460
|
+
hideTimer.current = setTimeout(() => {
|
|
461
|
+
if (playerRef.current && !scrubbing.current && !settingsOpen) {
|
|
462
|
+
// Only hide while actually playing.
|
|
463
|
+
if (playerRef.current.getTelemetry().playbackState === 'PLAYING')
|
|
464
|
+
setControlsVisible(false);
|
|
465
|
+
}
|
|
466
|
+
}, autoHideDelay);
|
|
467
|
+
}, [settingsOpen, autoHideDelay]);
|
|
468
|
+
useEffect(() => () => { if (hideTimer.current)
|
|
469
|
+
clearTimeout(hideTimer.current); }, []);
|
|
470
|
+
// ── Keyboard shortcuts (document-level, gated to hover/fullscreen) ─
|
|
471
|
+
useEffect(() => {
|
|
472
|
+
const onKey = (e) => {
|
|
473
|
+
const active = hoveredRef.current || document.fullscreenElement === containerRef.current;
|
|
474
|
+
if (!active)
|
|
475
|
+
return;
|
|
476
|
+
const tgt = e.target;
|
|
477
|
+
if (tgt && /^(INPUT|TEXTAREA|SELECT)$/.test(tgt.tagName))
|
|
478
|
+
return;
|
|
479
|
+
switch (e.key) {
|
|
480
|
+
case ' ':
|
|
481
|
+
case 'k':
|
|
482
|
+
e.preventDefault();
|
|
483
|
+
togglePlay();
|
|
484
|
+
break;
|
|
485
|
+
case 'ArrowLeft':
|
|
486
|
+
e.preventDefault();
|
|
487
|
+
relSeek(-5);
|
|
488
|
+
break;
|
|
489
|
+
case 'ArrowRight':
|
|
490
|
+
e.preventDefault();
|
|
491
|
+
relSeek(5);
|
|
492
|
+
break;
|
|
493
|
+
case 'ArrowUp':
|
|
494
|
+
e.preventDefault();
|
|
495
|
+
applyVolume((muted ? 0 : volume) + 0.05);
|
|
496
|
+
break;
|
|
497
|
+
case 'ArrowDown':
|
|
498
|
+
e.preventDefault();
|
|
499
|
+
applyVolume((muted ? 0 : volume) - 0.05);
|
|
500
|
+
break;
|
|
501
|
+
case 'm':
|
|
502
|
+
case 'M':
|
|
503
|
+
case 'ь':
|
|
504
|
+
toggleMute();
|
|
505
|
+
break;
|
|
506
|
+
case 'f':
|
|
507
|
+
case 'F':
|
|
508
|
+
case 'а':
|
|
509
|
+
toggleFullscreen();
|
|
510
|
+
break;
|
|
511
|
+
default: return;
|
|
512
|
+
}
|
|
513
|
+
revealControls();
|
|
514
|
+
};
|
|
515
|
+
window.addEventListener('keydown', onKey);
|
|
516
|
+
return () => window.removeEventListener('keydown', onKey);
|
|
517
|
+
}, [togglePlay, relSeek, applyVolume, toggleMute, toggleFullscreen, revealControls, muted, volume]);
|
|
518
|
+
const displayTime = scrubTime !== null ? scrubTime : currentTime;
|
|
519
|
+
const volPct = muted ? 0 : volume * 100;
|
|
520
|
+
const barHidden = isPlaying && !controlsVisible && !settingsOpen;
|
|
521
|
+
return (_jsxs("div", { ref: containerRef, tabIndex: 0, onMouseEnter: () => { hoveredRef.current = true; }, onMouseMove: revealControls, onMouseLeave: () => { hoveredRef.current = false; if (isPlaying && !settingsOpen)
|
|
522
|
+
setControlsVisible(false); }, style: { ['--yy-accent']: accentColor }, className: `yyv-root${barHidden ? ' yyv-nocursor' : ''} ${className}`, children: [_jsx("canvas", { ref: canvasRef, className: "yyv-canvas", onClick: togglePlay }), _jsx("video", { ref: pipVideoRef, muted: true, playsInline: true, className: "yyv-pipvideo" }), ((badges && badges.length > 0) || overlayTopLeft) && (_jsxs("div", { className: "yyv-overlay-tl", children: [badges?.map((b, i) => (_jsx(Badge, { label: b.label, variant: b.variant }, i))), overlayTopLeft] })), overlayTopRight && (_jsx("div", { className: "yyv-overlay-tr", children: overlayTopRight })), (!isReady || isBuffering) && !hasError && (_jsx("div", { className: "yyv-spin", style: { color: accentColor }, children: _jsx(Spinner, {}) })), isReady && !isPlaying && !isBuffering && !hasError && (_jsx(Button, { variant: "ghost", className: "yyv-center", onClick: togglePlay, "aria-label": "Play", style: { color: accentColor }, children: _jsx("span", { style: { display: 'flex', transform: 'scale(1.4)' }, children: _jsx(PlayIcon, {}) }) })), hasError && _jsx("div", { className: "yyv-error", children: "Playback error" }), _jsxs("div", { className: `yyv-bar${barHidden ? ' yyv-hidden' : ''}`, onMouseEnter: () => { if (hideTimer.current)
|
|
523
|
+
clearTimeout(hideTimer.current); }, children: [show('timeline') && (_jsx("div", { className: "yyv-tlrow", children: isLive ? (_jsxs("div", { className: "yyv-live", children: [_jsx("span", { className: "yyv-livedot" }), t.live] })) : (_jsx(Timeline, { currentTime: displayTime, duration: duration, buffered: buffered, accent: accentColor, onScrubStart: () => { scrubbing.current = true; }, onScrubMove: (tt) => setScrubTime(tt), onScrubEnd: () => { scrubbing.current = false; setScrubTime(null); }, onSeek: (tt) => { playerRef.current?.seek(tt); setCurrentTime(tt); } })) })), _jsxs("div", { className: "yyv-row", children: [show('play') && (_jsx(Button, { variant: "ghost", className: "yyv-btn", onClick: togglePlay, "aria-label": isPlaying ? 'Pause' : 'Play', children: isPlaying ? _jsx(PauseIcon, {}) : _jsx(PlayIcon, {}) })), show('volume') && (_jsxs("div", { className: "yyv-vol", children: [_jsx(Button, { variant: "ghost", className: "yyv-btn", onClick: toggleMute, "aria-label": muted ? 'Unmute' : 'Mute', children: muted ? _jsx(VolumeMuteIcon, {}) : _jsx(VolumeHighIcon, {}) }), _jsx(Slider, { value: volPct, onChange: (val) => applyVolume(val / 100), className: "yyv-volrange" })] })), show('time') && (_jsx("span", { className: "yyv-time", children: isLive ? t.live : `${formatTime(displayTime)} / ${formatTime(duration)}` })), _jsx("div", { className: "yyv-spacer" }), show('speed') && !show('settings') && (_jsx(SpeedQuick, { rate: rate, accent: accentColor, onPick: applyRate })), show('settings') && (_jsxs("div", { style: { position: 'relative' }, children: [_jsx(Button, { variant: "ghost", className: "yyv-btn", onClick: () => { setSettingsOpen((s) => !s); revealControls(); }, "aria-label": t.settings, style: { transform: settingsOpen ? 'rotate(45deg)' : undefined }, children: _jsx(GearIcon, {}) }), settingsOpen && (_jsx(SettingsMenu, { lang: lang, accent: accentColor, rate: rate, autoplay: autoplay, loop: loop, onRate: applyRate, onAutoplay: (v) => { setAutoplay(v); writeStore(K('autoplay'), v); }, onLoop: (v) => { setLoop(v); writeStore(K('loop'), v); } }))] })), show('pip') && pipSupported && (_jsx(Button, { variant: "ghost", className: "yyv-btn", onClick: togglePip, "aria-label": "Picture in picture", children: _jsx(PipIcon, {}) })), show('fullscreen') && (_jsx(Button, { variant: "ghost", className: "yyv-btn", onClick: toggleFullscreen, "aria-label": "Fullscreen", children: isFullscreen ? _jsx(FullscreenExitIcon, {}) : _jsx(FullscreenIcon, {}) }))] })] })] }));
|
|
524
|
+
};
|
|
525
|
+
// Compact inline speed cycler used when the gear menu is hidden.
|
|
526
|
+
const SpeedQuick = ({ rate, accent, onPick }) => {
|
|
527
|
+
const next = () => {
|
|
528
|
+
const i = PLAYBACK_RATES.indexOf(rate);
|
|
529
|
+
onPick(PLAYBACK_RATES[(i + 1) % PLAYBACK_RATES.length]);
|
|
530
|
+
};
|
|
531
|
+
return (_jsxs(Button, { variant: "ghost", className: "yyv-btn", onClick: next, style: { font: '700 12px/1 ui-monospace,monospace', color: rate !== 1 ? accent : '#fff' }, children: [rate, "\u00D7"] }));
|
|
532
|
+
};
|
|
533
|
+
const SettingsMenu = ({ lang, accent, rate, autoplay, loop, onRate, onAutoplay, onLoop }) => {
|
|
534
|
+
const t = STRINGS[lang];
|
|
535
|
+
const Toggle = ({ label, on, onClick }) => (_jsxs(Button, { variant: "ghost", className: "yyv-mi", onClick: onClick, children: [_jsx("span", { children: label }), _jsx("span", { style: { fontWeight: 700, fontSize: 10, color: on ? accent : '#888' }, children: on ? t.on : t.off })] }));
|
|
536
|
+
return (_jsxs("div", { className: "yyv-menu", children: [_jsx(Toggle, { label: t.autoplay, on: autoplay, onClick: () => onAutoplay(!autoplay) }), _jsx(Toggle, { label: t.loop, on: loop, onClick: () => onLoop(!loop) }), _jsx("div", { className: "yyv-sep" }), _jsx("div", { className: "yyv-mlabel", children: t.speed }), PLAYBACK_RATES.map((r) => (_jsxs(Button, { variant: "ghost", className: "yyv-mi", onClick: () => onRate(r), children: [_jsx("span", { children: r === 1 ? t.normal : `${r}×` }), rate === r && _jsx("span", { style: { color: accent, display: 'flex' }, children: _jsx(CheckIcon, {}) })] }, r)))] }));
|
|
537
|
+
};
|
|
538
|
+
//# sourceMappingURL=YumYumPlayerView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"YumYumPlayerView.js","sourceRoot":"","sources":["../src/YumYumPlayerView.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export { YumYumPlayerView } from './YumYumPlayerView.js';
|
|
3
|
+
export type { YumYumPlayerViewProps, PlayerHandle, PlayerControlKey } from './YumYumPlayerView.js';
|
|
4
|
+
export interface BadgeProps {
|
|
5
|
+
label: string;
|
|
6
|
+
variant?: 'primary' | 'warning' | 'neutral' | 'rec';
|
|
7
|
+
}
|
|
8
|
+
export declare const Badge: React.FC<BadgeProps>;
|
|
9
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
10
|
+
active?: boolean;
|
|
11
|
+
variant?: 'default' | 'ghost';
|
|
12
|
+
}
|
|
13
|
+
export declare const Button: React.FC<ButtonProps>;
|
|
14
|
+
export interface SliderProps {
|
|
15
|
+
value: number;
|
|
16
|
+
onChange: (value: number) => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
hoverPreview?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const Slider: React.FC<SliderProps>;
|
|
21
|
+
export declare const Spinner: React.FC;
|
|
22
|
+
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
23
|
+
}
|
|
24
|
+
export declare const Input: React.FC<InputProps>;
|
|
25
|
+
export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|
26
|
+
}
|
|
27
|
+
export declare const Select: React.FC<SelectProps>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
// Full YouTube-style player chrome (timeline, volume, speed, autoplay, PiP, fullscreen).
|
|
5
|
+
export { YumYumPlayerView } from './YumYumPlayerView.js';
|
|
6
|
+
const STYLE_ID = 'yyp-primitives-styles';
|
|
7
|
+
const STYLE = `
|
|
8
|
+
.yyp-badge{display:inline-flex;align-items:center;padding:2px 6px;border-radius:3px;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;border:1px solid}
|
|
9
|
+
.yyp-badge-primary{background:rgba(0,255,102,.06);color:var(--yyp-accent,#00ff66);border-color:rgba(0,255,102,.3)}
|
|
10
|
+
.yyp-badge-warning{background:rgba(255,173,0,.08);color:var(--yyp-warning,#ffad00);border-color:rgba(255,173,0,.35)}
|
|
11
|
+
.yyp-badge-neutral{background:var(--yyp-surface,#0a0a0a);color:var(--yyp-text-secondary,#a0a0a0);border-color:var(--yyp-border,#1a1a1a)}
|
|
12
|
+
.yyp-badge-rec{background:rgba(255,69,58,.08);color:#ff453a;border-color:rgba(255,69,58,.4);animation:yyp-pulse 1.4s infinite}
|
|
13
|
+
|
|
14
|
+
.yyp-btn{display:inline-flex;align-items:center;justify-content:center;border-radius:4px;border:1px solid;cursor:pointer;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;transition:all .2s;color:var(--yyp-text,#fff)}
|
|
15
|
+
.yyp-btn-default{background:var(--yyp-surface,#0a0a0a);border-color:var(--yyp-border,#1a1a1a)}
|
|
16
|
+
.yyp-btn-default:hover{background:var(--yyp-surface-hover,#121212);border-color:rgba(160,160,160,.3)}
|
|
17
|
+
.yyp-btn-active{background:rgba(0,255,102,.05);border-color:var(--yyp-accent,#00ff66);color:var(--yyp-accent,#00ff66);box-shadow:0 0 8px rgba(0,255,102,.1)}
|
|
18
|
+
.yyp-btn-ghost{border:none;background:transparent;padding:0;height:auto}
|
|
19
|
+
.yyp-btn-ghost:hover{background:rgba(255,255,255,.05)}
|
|
20
|
+
.yyp-btn:active{transform:scale(.95)}
|
|
21
|
+
|
|
22
|
+
.yyp-input{background:#000;border:1px solid var(--yyp-border,#1a1a1a);border-radius:4px;padding:8px 10px;color:#fff;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:10px;outline:none;transition:border-color .15s}
|
|
23
|
+
.yyp-input:focus{border-color:var(--yyp-accent,#00ff66)}
|
|
24
|
+
.yyp-input::placeholder{color:rgba(160,160,160,.45)}
|
|
25
|
+
|
|
26
|
+
.yyp-select{background:#000;border:1px solid var(--yyp-border,#1a1a1a);border-radius:4px;padding:6px 8px;color:#fff;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:10px;outline:none;transition:border-color .15s}
|
|
27
|
+
.yyp-select:focus{border-color:var(--yyp-accent,#00ff66)}
|
|
28
|
+
|
|
29
|
+
.yyp-slider{position:relative;height:6px;width:100%;background:rgba(255,255,255,.15);border-radius:999px;cursor:pointer;overflow:hidden;outline:none;user-select:none}
|
|
30
|
+
.yyp-slider-fill{position:absolute;height:100%;left:0;top:0;background:var(--yyp-accent,#00ff66);transition:background-color .15s}
|
|
31
|
+
.yyp-slider-handle{position:absolute;top:50%;transform:translate(-50%,-50%);height:10px;width:10px;border-radius:50%;background:#fff;border:1px solid var(--yyp-accent,#00ff66);box-shadow:0 0 3px rgba(0,0,0,.5);opacity:0;transition:opacity .15s}
|
|
32
|
+
.yyp-slider:hover .yyp-slider-handle,.yyp-slider:focus-visible .yyp-slider-handle{opacity:1}
|
|
33
|
+
|
|
34
|
+
.yyp-spinner{display:inline-flex;align-items:center;justify-content:center;pointer-events:none}
|
|
35
|
+
.yyp-spinner-svg{animation:yyp-rot 1s linear infinite;height:40px;width:40px;color:var(--yyp-accent,#00ff66)}
|
|
36
|
+
|
|
37
|
+
@keyframes yyp-rot{to{transform:rotate(360deg)}}
|
|
38
|
+
@keyframes yyp-pulse{0%,100%{opacity:1}50%{opacity:.3}}
|
|
39
|
+
`;
|
|
40
|
+
function ensureStyles() {
|
|
41
|
+
if (typeof document === 'undefined' || document.getElementById(STYLE_ID))
|
|
42
|
+
return;
|
|
43
|
+
const el = document.createElement('style');
|
|
44
|
+
el.id = STYLE_ID;
|
|
45
|
+
el.textContent = STYLE;
|
|
46
|
+
document.head.appendChild(el);
|
|
47
|
+
}
|
|
48
|
+
export const Badge = ({ label, variant = 'neutral' }) => {
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
ensureStyles();
|
|
51
|
+
}, []);
|
|
52
|
+
const getVariantClass = () => {
|
|
53
|
+
switch (variant) {
|
|
54
|
+
case 'primary':
|
|
55
|
+
return 'yyp-badge-primary';
|
|
56
|
+
case 'warning':
|
|
57
|
+
return 'yyp-badge-warning';
|
|
58
|
+
case 'rec':
|
|
59
|
+
return 'yyp-badge-rec';
|
|
60
|
+
default:
|
|
61
|
+
return 'yyp-badge-neutral';
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return (_jsx("span", { className: `yyp-badge ${getVariantClass()}`, children: label }));
|
|
65
|
+
};
|
|
66
|
+
export const Button = ({ children, active, variant = 'default', className = '', ...props }) => {
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
ensureStyles();
|
|
69
|
+
}, []);
|
|
70
|
+
const getVariantClass = () => {
|
|
71
|
+
if (variant === 'ghost') {
|
|
72
|
+
return 'yyp-btn-ghost';
|
|
73
|
+
}
|
|
74
|
+
return active ? 'yyp-btn-active' : 'yyp-btn-default';
|
|
75
|
+
};
|
|
76
|
+
return (_jsx("button", { className: `yyp-btn ${getVariantClass()} ${className}`, "aria-pressed": active, ...props, children: children }));
|
|
77
|
+
};
|
|
78
|
+
export const Slider = ({ value, onChange, className = '' }) => {
|
|
79
|
+
const containerRef = useRef(null);
|
|
80
|
+
const isDragging = useRef(false);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
ensureStyles();
|
|
83
|
+
}, []);
|
|
84
|
+
const handlePointerDown = (e) => {
|
|
85
|
+
if (!containerRef.current)
|
|
86
|
+
return;
|
|
87
|
+
isDragging.current = true;
|
|
88
|
+
containerRef.current.setPointerCapture(e.pointerId);
|
|
89
|
+
updateValue(e);
|
|
90
|
+
};
|
|
91
|
+
const handlePointerMove = (e) => {
|
|
92
|
+
if (!isDragging.current)
|
|
93
|
+
return;
|
|
94
|
+
updateValue(e);
|
|
95
|
+
};
|
|
96
|
+
const handlePointerUp = (e) => {
|
|
97
|
+
if (!isDragging.current)
|
|
98
|
+
return;
|
|
99
|
+
isDragging.current = false;
|
|
100
|
+
if (containerRef.current) {
|
|
101
|
+
try {
|
|
102
|
+
containerRef.current.releasePointerCapture(e.pointerId);
|
|
103
|
+
}
|
|
104
|
+
catch (err) { }
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const updateValue = (e) => {
|
|
108
|
+
if (!containerRef.current)
|
|
109
|
+
return;
|
|
110
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
111
|
+
const x = e.clientX - rect.left;
|
|
112
|
+
const pct = Math.max(0, Math.min(100, (x / rect.width) * 100));
|
|
113
|
+
onChange(pct);
|
|
114
|
+
};
|
|
115
|
+
const handleKeyDown = (e) => {
|
|
116
|
+
let step = 1;
|
|
117
|
+
if (e.shiftKey) {
|
|
118
|
+
step = 10;
|
|
119
|
+
}
|
|
120
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
onChange(Math.min(100, value + step));
|
|
123
|
+
}
|
|
124
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
|
|
125
|
+
e.preventDefault();
|
|
126
|
+
onChange(Math.max(0, value - step));
|
|
127
|
+
}
|
|
128
|
+
else if (e.key === 'Home') {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
onChange(0);
|
|
131
|
+
}
|
|
132
|
+
else if (e.key === 'End') {
|
|
133
|
+
e.preventDefault();
|
|
134
|
+
onChange(100);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return (_jsxs("div", { ref: containerRef, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onKeyDown: handleKeyDown, tabIndex: 0, role: "slider", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": Math.round(value), className: `yyp-slider ${className}`, children: [_jsx("div", { className: "yyp-slider-fill", style: { width: `${value}%` } }), _jsx("div", { className: "yyp-slider-handle", style: { left: `calc(${value}% - 5px)` } })] }));
|
|
138
|
+
};
|
|
139
|
+
// ==================== BUFFERING SPINNER ====================
|
|
140
|
+
export const Spinner = () => {
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
ensureStyles();
|
|
143
|
+
}, []);
|
|
144
|
+
return (_jsx("div", { className: "yyp-spinner", role: "status", "aria-label": "Loading...", children: _jsxs("svg", { className: "yyp-spinner-svg", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { style: { opacity: 0.25 }, cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3" }), _jsx("path", { style: { opacity: 0.75 }, fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }) }));
|
|
145
|
+
};
|
|
146
|
+
export const Input = ({ className = '', ...props }) => {
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
ensureStyles();
|
|
149
|
+
}, []);
|
|
150
|
+
return (_jsx("input", { className: `yyp-input ${className}`, ...props }));
|
|
151
|
+
};
|
|
152
|
+
export const Select = ({ children, className = '', ...props }) => {
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
ensureStyles();
|
|
155
|
+
}, []);
|
|
156
|
+
return (_jsx("select", { className: `yyp-select ${className}`, ...props, children: children }));
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yumyum-player/ui",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"author": "Vokinlemxela",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"clean": "rm -rf dist",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
25
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"react": "^18.3.1",
|
|
29
|
+
"react-dom": "^18.3.1",
|
|
30
|
+
"@types/react": "^18.3.3",
|
|
31
|
+
"@types/react-dom": "^18.3.0",
|
|
32
|
+
"@testing-library/react": "^16.1.0",
|
|
33
|
+
"@testing-library/dom": "^10.4.0",
|
|
34
|
+
"jsdom": "^25.0.1",
|
|
35
|
+
"vitest": "^4.1.8",
|
|
36
|
+
"typescript": "^5.4.5"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md",
|
|
44
|
+
"README.ru.md"
|
|
45
|
+
]
|
|
46
|
+
}
|