@base-ui-components/react
Version:
Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.
88 lines (86 loc) • 3.23 kB
JavaScript
'use client';
import * as React from 'react';
import { useOnMount } from '@base-ui-components/utils/useOnMount';
import { valueToPercent } from "../../utils/valueToPercent.js";
import { useRenderElement } from "../../utils/useRenderElement.js";
import { useSliderRootContext } from "../root/SliderRootContext.js";
import { sliderStateAttributesMapping } from "../root/stateAttributesMapping.js";
function getInsetStyles(vertical, range, start, end, renderBeforeHydration, mounted) {
const visibility = start === undefined || range && end === undefined ? 'hidden' : undefined;
const startEdge = vertical ? 'bottom' : 'insetInlineStart';
const mainSide = vertical ? 'height' : 'width';
const crossSide = vertical ? 'width' : 'height';
const styles = {
visibility: renderBeforeHydration && !mounted ? 'hidden' : visibility,
position: vertical ? 'absolute' : 'relative',
[crossSide]: 'inherit'
};
styles['--start-position'] = `${start ?? 0}%`;
if (!range) {
styles[startEdge] = 0;
styles[mainSide] = 'var(--start-position)';
return styles;
}
styles['--relative-size'] = `${(end ?? 0) - (start ?? 0)}%`;
styles[startEdge] = 'var(--start-position)';
styles[mainSide] = 'var(--relative-size)';
return styles;
}
function getCenteredStyles(vertical, range, start, end) {
const startEdge = vertical ? 'bottom' : 'insetInlineStart';
const mainSide = vertical ? 'height' : 'width';
const crossSide = vertical ? 'width' : 'height';
const styles = {
position: vertical ? 'absolute' : 'relative',
[crossSide]: 'inherit'
};
if (!range) {
styles[startEdge] = 0;
styles[mainSide] = `${start}%`;
return styles;
}
const size = end - start;
styles[startEdge] = `${start}%`;
styles[mainSide] = `${size}%`;
return styles;
}
/**
* Visualizes the current value of the slider.
* Renders a `<div>` element.
*
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider)
*/
export const SliderIndicator = /*#__PURE__*/React.forwardRef(function SliderIndicator(componentProps, forwardedRef) {
const {
render,
className,
...elementProps
} = componentProps;
const {
indicatorPosition,
inset,
max,
min,
orientation,
renderBeforeHydration,
state,
values
} = useSliderRootContext();
const [isMounted, setIsMounted] = React.useState(false);
useOnMount(() => setIsMounted(true));
const vertical = orientation === 'vertical';
const range = values.length > 1;
const style = inset ? getInsetStyles(vertical, range, indicatorPosition[0], indicatorPosition[1], renderBeforeHydration, isMounted) : getCenteredStyles(vertical, range, valueToPercent(values[0], min, max), valueToPercent(values[values.length - 1], min, max));
const element = useRenderElement('div', componentProps, {
state,
ref: forwardedRef,
props: [{
['data-base-ui-slider-indicator']: renderBeforeHydration ? '' : undefined,
style,
suppressHydrationWarning: renderBeforeHydration || undefined
}, elementProps],
stateAttributesMapping: sliderStateAttributesMapping
});
return element;
});
if (process.env.NODE_ENV !== "production") SliderIndicator.displayName = "SliderIndicator";