Files
v10/dist/dev/ui/volume-slider/volume-slider-root.js

120 lines
4.0 KiB
JavaScript

"use client";
import { useLocale, useTranslator } from "../../i18n/context.js";
import { usePlayer } from "../../player/context.js";
import { useLatestRef } from "../../utils/use-latest-ref.js";
import { renderElement } from "../../utils/use-render.js";
import { useSlider } from "../hooks/use-slider.js";
import { SliderProvider } from "../slider/context.js";
import { createWheelStep, getSliderCSSVars, logMissingFeature, selectVolume } from "@videojs/core/dom";
import { translateText } from "@videojs/core/i18n";
import { forwardRef, useCallback, useRef, useState } from "react";
import { listen } from "@videojs/utils/dom";
import { jsx } from "react/jsx-runtime";
import { VolumeSliderCore, VolumeSliderDataAttrs } from "@videojs/core";
//#region src/ui/volume-slider/volume-slider-root.tsx
const noopVolume = {
volume: 0,
muted: false,
volumeAvailability: "unsupported",
setVolume: () => 0,
toggleMuted: () => false
};
const VolumeSliderRoot = forwardRef(function VolumeSliderRoot(componentProps, forwardedRef) {
const { render, className, style, label, orientation, step = VolumeSliderCore.defaultProps.step, largeStep = VolumeSliderCore.defaultProps.largeStep, wheelStep = VolumeSliderCore.defaultProps.wheelStep, disabled, thumbAlignment, onDragStart, onDragEnd, ...elementProps } = componentProps;
const volume = usePlayer(selectVolume);
const translator = useTranslator();
const locale = useLocale();
const [core] = useState(() => new VolumeSliderCore());
core.setProps({
label,
orientation,
step,
largeStep,
wheelStep,
disabled,
thumbAlignment
});
core.setFormatLocale(locale);
const volumeRef = useLatestRef(volume);
const disabledRef = useLatestRef(disabled);
const getPercent = () => (volumeRef.current?.volume ?? 0) * 100;
const getStepPercent = () => core.getStepPercent();
const setVolume = (percent) => volumeRef.current?.setVolume(percent / 100);
const { state, cssVars, rootRef, thumbRef, rootProps, rootStyle, thumbProps } = useSlider({
computeState: (input) => {
core.setInput(input);
core.setMedia(volume ?? noopVolume);
return core.getState();
},
getPercent,
getStepPercent,
getLargeStepPercent: () => core.getLargeStepPercent(),
orientation,
disabled,
adjustPercent: (rawPercent, thumbSize, trackSize) => core.adjustPercentForAlignment(rawPercent, thumbSize, trackSize),
getCSSVars: getSliderCSSVars,
onValueChange: setVolume,
onValueCommit: setVolume,
onDragStart,
onDragEnd
});
const [wheelHandler] = useState(() => createWheelStep({
isDisabled: () => !!disabledRef.current || !volumeRef.current,
getPercent: () => (volumeRef.current?.volume ?? 0) * 100,
getStepPercent: () => core.getWheelStepPercent(),
onValueChange: (percent) => volumeRef.current?.setVolume(percent / 100)
}));
const wheelCleanupRef = useRef(null);
const wheelRef = useCallback((element) => {
wheelCleanupRef.current?.();
wheelCleanupRef.current = null;
if (element) wheelCleanupRef.current = listen(element, "wheel", wheelHandler.onWheel, { passive: false });
}, [wheelHandler]);
if (!volume) {
logMissingFeature("VolumeSlider", "volume");
return null;
}
return /* @__PURE__ */ jsx(SliderProvider, {
value: {
state,
pointerValue: core.valueFromPercent(state.pointerPercent),
thumbRef,
thumbProps,
stateAttrMap: VolumeSliderDataAttrs,
getAttrs: (sliderState) => {
const attrs = core.getAttrs(sliderState);
return {
...attrs,
"aria-label": translateText(attrs["aria-label"], translator),
"aria-valuetext": translateText(attrs["aria-valuetext"], translator, core.getValueTextParams(sliderState))
};
},
formatValue: (value) => `${Math.round(value)}%`
},
children: renderElement("div", {
render,
className,
style
}, {
state,
stateAttrMap: VolumeSliderDataAttrs,
ref: [
forwardedRef,
rootRef,
wheelRef
],
props: [
{ style: {
...cssVars,
...rootStyle
} },
rootProps,
elementProps
]
})
});
});
//#endregion
export { VolumeSliderRoot };
//# sourceMappingURL=volume-slider-root.js.map