import type { Domain, ScaleType } from '@h5web/shared'; import { useState } from 'react'; import { FiSkipBack, FiSkipForward } from 'react-icons/fi'; import ReactSlider from 'react-slider'; import { getSafeDomain } from '../../../vis/heatmap/utils'; import type { DomainErrors } from '../../../vis/models'; import { clampBound, createAxisScale, extendDomain } from '../../../vis/utils'; import styles from './DomainSlider.module.css'; import Thumb from './Thumb'; import Track from './Track'; const SLIDER_RANGE: Domain = [1, 100]; const EXTEND_FACTOR = 0.3; interface Props { value: Domain; dataDomain: Domain; safeVisDomain: Domain; scaleType: ScaleType; errors: DomainErrors; isAutoMin: boolean; isAutoMax: boolean; onChange: (newValue: Domain) => void; onAfterChange: (hasMinChanged: boolean, hasMaxChanged: boolean) => void; } function ScaledSlider(props: Props) { const { value, dataDomain, safeVisDomain, scaleType, errors, isAutoMin, isAutoMax, } = props; const { onChange, onAfterChange: onDone } = props; const { minGreater, minError, maxError } = errors; const sliderExtent = extendDomain(safeVisDomain, EXTEND_FACTOR, scaleType); const scale = createAxisScale(scaleType, { domain: sliderExtent.map((val) => clampBound(val)), range: SLIDER_RANGE, clamp: true, }); const [safeValue] = getSafeDomain(value, dataDomain, scaleType); const scaledValue = safeValue.map(scale).map(Math.round) as Domain; const [beforeChangeValue, setBeforeChangeValue] = useState(scaledValue); function handleChange(newScaledValue: Domain, done = false) { const [newScaledMin, newScaledMax] = newScaledValue; const hasMinChanged = newScaledMin !== beforeChangeValue[0]; const hasMaxChanged = newScaledMax !== beforeChangeValue[1]; const newValue: Domain = [ hasMinChanged ? scale.invert(newScaledMin) : value[0], hasMaxChanged ? scale.invert(newScaledMax) : value[1], ]; if (done) { onDone(hasMinChanged, hasMaxChanged); } else { onChange(newValue); } } return ( handleChange(bounds)} onAfterChange={(bounds) => handleChange(bounds, true)} renderThumb={(thumbProps, { index }) => ( )} renderTrack={({ key }, { index }) => index === 0 ? ( ) : null } /> ); } export default ScaledSlider;