Files
v10/dist/dev/ui/live-button/live-button.js

96 lines
3.2 KiB
JavaScript

"use client";
import { useTranslator } from "../../i18n/context.js";
import { usePlayer } from "../../player/context.js";
import { renderElement } from "../../utils/use-render.js";
import { useButton } from "../hooks/use-button.js";
import { useOptionalTooltipContext } from "../tooltip/context.js";
import { logMissingFeature, selectBuffer, selectLive, selectTime } from "@videojs/core/dom";
import { translateText } from "@videojs/core/i18n";
import { forwardRef, useLayoutEffect, useState } from "react";
import { LiveButtonCore, LiveButtonDataAttrs } from "@videojs/core";
//#region src/ui/live-button/live-button.tsx
const DISPLAY_NAME = "LiveButton";
/**
* A button that indicates live status and seeks to the live edge when
* pressed. Exposes `data-live` while the stream is live (or DVR) and
* `data-live-edge` while playing at the live edge so skins can style a
* red-dot ↔ grey-dot treatment.
*
* Selects from `live`, `time`, and `buffer` features and composes them
* itself rather than going through `createMediaButton`, since the LiveButton
* needs three feature slices to detect the live edge and seek.
*
* Displays the translated live badge when no children are provided.
*
* @example
* ```tsx
* <LiveButton />
* ```
*
* @see https://github.com/video-dev/media-ui-extensions/blob/main/proposals/0007-live-edge.md
*/
const LiveButton = forwardRef(function LiveButton(componentProps, forwardedRef) {
const { children, render, className, style, label, disabled, ...elementProps } = componentProps;
const live = usePlayer(selectLive);
const time = usePlayer(selectTime);
const buffer = usePlayer(selectBuffer);
const media = live && time && buffer ? {
currentTime: time.currentTime,
seek: time.seek,
seekable: buffer.seekable,
liveEdgeStart: live.liveEdgeStart,
targetLiveWindow: live.targetLiveWindow
} : null;
const tooltipCtx = useOptionalTooltipContext();
const translator = useTranslator();
const [core] = useState(() => new LiveButtonCore());
core.setProps({
label,
disabled
});
const { getButtonProps, buttonRef } = useButton({
displayName: DISPLAY_NAME,
onActivate: () => {
if (media) core.seekToLive(media);
},
isDisabled: () => !!disabled || !media
});
if (media) core.setMedia(media);
const state = media ? core.getState() : null;
const labelText = state ? translateText(core.getLabel(state), translator) : void 0;
useLayoutEffect(() => {
if (!tooltipCtx) return;
tooltipCtx.setContent(labelText ? { label: labelText } : void 0);
return () => tooltipCtx.setContent(void 0);
}, [tooltipCtx, labelText]);
if (!media || !state) {
logMissingFeature(DISPLAY_NAME, selectLive.displayName ?? "live");
return null;
}
const attrs = core.getAttrs(state);
const labelAttr = attrs["aria-label"];
const content = children ?? translateText(LiveButtonCore.defaultText, translator);
return renderElement("button", {
render,
className,
style
}, {
state,
stateAttrMap: LiveButtonDataAttrs,
ref: [forwardedRef, buttonRef],
props: [
attrs,
{
children: content,
...elementProps,
"aria-label": labelAttr ? translateText(labelAttr, translator) : labelAttr
},
getButtonProps()
]
});
});
LiveButton.displayName = DISPLAY_NAME;
//#endregion
export { LiveButton };
//# sourceMappingURL=live-button.js.map