UNPKG

@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
'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";