import React from 'react';
import { PanResponder } from 'react-native';
import {
FormControlContext,
IFormControlContext,
} from '../../composites/FormControl';
import { Box } from '../../primitives';
import { usePropsConfig } from '../../../theme';
import type { ISliderProps } from './props';
export const SliderContext = React.createContext({});
type StateType = {
barSize: number | null;
deltaValue: number;
value: number;
};
class NBSlider extends React.Component<
ISliderProps & {
thumbSize?: number;
sliderSize?: number;
activeColor?: string;
},
StateType
> {
static contextType = SliderContext;
state = {
barSize: null,
deltaValue: 0,
value: this.props.defaultValue || 0,
};
panResponder = PanResponder.create({
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderMove: (_event, gestureState) =>
!(this.props.isDisabled || this.props.isReadOnly) &&
this.onMove(gestureState),
onPanResponderRelease: () => this.onEndMove(),
onPanResponderTerminate: () => {},
});
onMove(gestureState: any) {
const { barSize } = this.state;
const newDeltaValue = this.getValueFromBottomOffset(
gestureState.dx,
barSize,
this.props.min || 0,
this.props.max || 100
);
this.props.onChange &&
this.props.onChange(this.state.value + newDeltaValue);
this.setState({
deltaValue: newDeltaValue,
});
}
onEndMove() {
const { value, deltaValue } = this.state;
this.props.onChangeEnd && this.props.onChangeEnd(value + deltaValue);
this.setState({ value: value + deltaValue, deltaValue: 0 });
}
onBarLayout = (event: any) => {
const { width: barSize } = event.nativeEvent.layout;
this.setState({ barSize });
};
capValueWithinRange = (value: number, range: number[]) => {
if (value < range[0]) return range[0];
if (value > range[1]) return range[1];
return value;
};
getValueFromBottomOffset = (
offset: number,
barSize: number | null,
rangeMin: number,
rangeMax: number
) => {
if (barSize === null) return 0;
return ((rangeMax - rangeMin) * offset) / barSize;
};
getOffsetFromValue = (
value: number,
rangeMin: number,
rangeMax: number,
barSize: number | null
) => {
if (barSize === null) return 0;
const valueOffset = value - rangeMin;
const totalRange = rangeMax - rangeMin;
const percentage = valueOffset / totalRange;
return barSize * percentage;
};
render() {
const { value, deltaValue, barSize } = this.state;
const cappedValue = this.capValueWithinRange(value + deltaValue, [
this.props.min || 0,
this.props.max || 100,
]);
const sliderOffset = this.getOffsetFromValue(
cappedValue,
this.props.min || 0,
this.props.max || 100,
barSize
);
return (
{this.state.barSize && this.state.value && this.props.children}
);
}
}
const Slider = ({ ...props }: ISliderProps) => {
const formControlContext: IFormControlContext = React.useContext(
FormControlContext
);
const newProps = usePropsConfig('Slider', {
...formControlContext,
...props,
});
return ;
};
export default Slider;