mirror of
https://github.com/zoriya/v10.git
synced 2026-08-12 08:59:02 +00:00
63 lines
2.5 KiB
JavaScript
63 lines
2.5 KiB
JavaScript
"use client";
|
|
import { useLatestRef } from "../../utils/use-latest-ref.js";
|
|
import { useDestroy } from "../../utils/use-destroy.js";
|
|
import { useForceRender } from "../../utils/use-force-render.js";
|
|
import { createSlider } from "@videojs/core/dom";
|
|
import { useSnapshot } from "@videojs/store/react";
|
|
import { useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
import { isRTL } from "@videojs/utils/dom";
|
|
//#region src/ui/hooks/use-slider.ts
|
|
/**
|
|
* Manages slider input lifecycle for React.
|
|
*
|
|
* Wraps `createSlider()` from `@videojs/core/dom` and subscribes to its
|
|
* input state via `useSnapshot`. Returns split props for the root
|
|
* (pointer events) and thumb (keyboard/focus) elements.
|
|
*/
|
|
function useSlider(options) {
|
|
const optionsRef = useLatestRef(options);
|
|
const rootElementRef = useRef(null);
|
|
const thumbElementRef = useRef(null);
|
|
const forceRender = useForceRender();
|
|
const [slider] = useState(() => {
|
|
return createSlider({
|
|
getElement: () => rootElementRef.current,
|
|
getThumbElement: () => thumbElementRef.current,
|
|
getOrientation: () => optionsRef.current.orientation ?? "horizontal",
|
|
isRTL: () => rootElementRef.current ? isRTL(rootElementRef.current) : false,
|
|
isDisabled: () => optionsRef.current.disabled ?? false,
|
|
getPercent: () => optionsRef.current.getPercent(),
|
|
getStepPercent: () => optionsRef.current.getStepPercent(),
|
|
getLargeStepPercent: () => optionsRef.current.getLargeStepPercent(),
|
|
changeThrottle: optionsRef.current.changeThrottle,
|
|
adjustPercent: optionsRef.current.adjustPercent,
|
|
onValueChange: (percent) => optionsRef.current.onValueChange?.(percent),
|
|
onValueCommit: (percent) => optionsRef.current.onValueCommit?.(percent),
|
|
onDragStart: () => optionsRef.current.onDragStart?.(),
|
|
onDragEnd: () => optionsRef.current.onDragEnd?.()
|
|
});
|
|
});
|
|
useDestroy(slider);
|
|
const input = useSnapshot(slider.input);
|
|
const state = options.computeState(input);
|
|
useLayoutEffect(() => {
|
|
if (state.thumbAlignment === "edge" && rootElementRef.current && thumbElementRef.current) forceRender();
|
|
}, [state.thumbAlignment]);
|
|
return {
|
|
state,
|
|
cssVars: options.getCSSVars(slider.adjustForAlignment(state)),
|
|
rootRef: useCallback((element) => {
|
|
rootElementRef.current = element;
|
|
}, []),
|
|
thumbRef: useCallback((element) => {
|
|
thumbElementRef.current = element;
|
|
}, []),
|
|
rootProps: slider.rootProps,
|
|
rootStyle: slider.rootStyle,
|
|
thumbProps: slider.thumbProps
|
|
};
|
|
}
|
|
//#endregion
|
|
export { useSlider };
|
|
|
|
//# sourceMappingURL=use-slider.js.map
|