feat: release v0.0.1
This commit is contained in:
145
dist/react/video-player/components/video-js/plugins/skip-buttons/index.js
vendored
Normal file
145
dist/react/video-player/components/video-js/plugins/skip-buttons/index.js
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
// skipButtonsPlugin.tsx
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import videojs from "video.js";
|
||||
import BackwardSvg from "./skip-backward.svg";
|
||||
import ForwardSvg from "./skip-forward.svg";
|
||||
import "./skip-buttons.css";
|
||||
import { numWord } from "../../../../shared/math";
|
||||
const renderSvg = (asset) => {
|
||||
if (typeof asset === "string") {
|
||||
return _jsx("img", { src: asset, alt: "", "aria-hidden": "true" });
|
||||
}
|
||||
const SvgComponent = asset;
|
||||
return _jsx(SvgComponent, {});
|
||||
};
|
||||
const SkipButton = ({ player, skip, direction }) => {
|
||||
// Накопленная сумма перемотки
|
||||
const [accumulated, setAccumulated] = React.useState(0);
|
||||
// Храним ID таймера debounce
|
||||
const timerRef = React.useRef(null);
|
||||
// Используем ref для мгновенного доступа к накопленному значению
|
||||
const accumulatedRef = React.useRef(0);
|
||||
const handleClick = () => {
|
||||
// Вычисляем новое накопленное значение
|
||||
const newAccumulated = direction === "forward"
|
||||
? accumulatedRef.current + skip
|
||||
: accumulatedRef.current - skip;
|
||||
accumulatedRef.current = newAccumulated;
|
||||
setAccumulated(newAccumulated);
|
||||
// Сбрасываем предыдущий таймер
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
}
|
||||
// Устанавливаем debounce (500 мс)
|
||||
timerRef.current = setTimeout(() => {
|
||||
const currentTime = player.currentTime() || 0;
|
||||
const newTime = currentTime + accumulatedRef.current;
|
||||
player.currentTime(newTime);
|
||||
// Сбрасываем накопленное значение
|
||||
accumulatedRef.current = 0;
|
||||
setAccumulated(0);
|
||||
}, 500);
|
||||
};
|
||||
return (_jsxs("button", { onClick: handleClick, className: `vjs-skip-button vjs-skip-button-${direction}`, children: [_jsx("span", { className: "icon-placeholder", children: skip }), accumulated ? (_jsxs("div", { className: "scroll-info", children: [direction === "backward"
|
||||
? renderSvg(BackwardSvg)
|
||||
: renderSvg(ForwardSvg), `${Math.abs(accumulated)} ${numWord(accumulated, ["секунду", "секунды", "секунд"])}`] })) : null] }));
|
||||
};
|
||||
// Базовый Video.js компонент, обёртывающий React-компонент
|
||||
class SkipButtonComponent extends videojs.getComponent("Component") {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.reactRoot = null;
|
||||
}
|
||||
createEl() {
|
||||
const direction = this.options_.direction;
|
||||
const el = super.createEl("div", {
|
||||
className: `vjs-skip-button-component vjs-skip-${direction}`,
|
||||
});
|
||||
// Рендерим React-компонент сразу внутри созданного элемента
|
||||
this.reactRoot = createRoot(el);
|
||||
this.reactRoot.render(_jsx(SkipButton, { player: this.player(), skip: this.options_.skip, direction: direction }));
|
||||
return el;
|
||||
}
|
||||
dispose() {
|
||||
if (this.reactRoot) {
|
||||
this.reactRoot.unmount();
|
||||
this.reactRoot = null;
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
// Компонент для кнопки перемотки назад – задаём direction через options
|
||||
class SkipBackwardButtonComponent extends SkipButtonComponent {
|
||||
constructor(player, options) {
|
||||
options.direction = "backward";
|
||||
super(player, options);
|
||||
}
|
||||
}
|
||||
// Компонент для кнопки перемотки вперёд – задаём direction через options
|
||||
class SkipForwardButtonComponent extends SkipButtonComponent {
|
||||
constructor(player, options) {
|
||||
options.direction = "forward";
|
||||
super(player, options);
|
||||
}
|
||||
}
|
||||
// Регистрируем компоненты в Video.js
|
||||
videojs.registerComponent("SkipBackwardButtonComponent", SkipBackwardButtonComponent);
|
||||
videojs.registerComponent("SkipForwardButtonComponent", SkipForwardButtonComponent);
|
||||
// Плагин, который добавляет два отдельных компонента через player.addChild
|
||||
const skipButtonsPlugin = function (options) {
|
||||
const player = this;
|
||||
player.ready(() => {
|
||||
// 1) Добавляем кнопки
|
||||
player.addChild("SkipBackwardButtonComponent", { skip: options.skip });
|
||||
player.addChild("SkipForwardButtonComponent", { skip: options.skip });
|
||||
// 2) Вспомогательная функция, которая находит кнопку и вызывает click()
|
||||
const triggerSkipClick = (direction) => {
|
||||
// Ищем именно <button class="vjs-skip-button vjs-skip-button-{direction}">
|
||||
const selector = `.vjs-skip-button-${direction}`;
|
||||
const btn = player.el().querySelector(selector);
|
||||
if (btn)
|
||||
btn.click();
|
||||
};
|
||||
// 3) Обработка стрелок
|
||||
const onKeydown = (e) => {
|
||||
// Если фокус в инпуте/textarea/select или contenteditable — выходим
|
||||
const active = document.activeElement;
|
||||
const tag = active?.tagName;
|
||||
const isEditable = tag === "INPUT" ||
|
||||
tag === "TEXTAREA" ||
|
||||
tag === "SELECT" ||
|
||||
active?.getAttribute("contenteditable") === "true";
|
||||
if (isEditable)
|
||||
return;
|
||||
if (e.key === " " || e.code === "Space") {
|
||||
player.el()?.focus();
|
||||
e.preventDefault();
|
||||
if (player.paused())
|
||||
player.play();
|
||||
else
|
||||
player.pause();
|
||||
return;
|
||||
}
|
||||
if (e.key === "ArrowRight") {
|
||||
player.el()?.focus();
|
||||
e.preventDefault();
|
||||
triggerSkipClick("forward");
|
||||
}
|
||||
else if (e.key === "ArrowLeft") {
|
||||
player.el()?.focus();
|
||||
e.preventDefault();
|
||||
triggerSkipClick("backward");
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", onKeydown);
|
||||
// 4) Убираем слушатель при dispose
|
||||
player.on("dispose", () => {
|
||||
document.removeEventListener("keydown", onKeydown);
|
||||
});
|
||||
});
|
||||
};
|
||||
videojs.registerPlugin("skipButtons", skipButtonsPlugin);
|
||||
export default skipButtonsPlugin;
|
||||
//# sourceMappingURL=index.js.map
|
||||
Reference in New Issue
Block a user