UNPKG

@prosperitainova/dumbo-react-native

Version:
260 lines (258 loc) 6.86 kB
"use strict"; import React from 'react'; import { PanResponder, StyleSheet, View } from 'react-native'; import { defaultText } from '../../constants/defaultText'; import { styleReferenceBreaker } from '../../helpers'; import { getColor } from '../../styles/colors'; import { Text } from '../Text'; import { TextInput } from '../TextInput'; /** Props for Slider component */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * Slider component for rendering a slider between numbers * * {@link https://github.com/carbon-design-system/carbon-react-native/blob/main/example/src/Views/Slider.tsx | Example code} */ export class Slider extends React.Component { state = { active: false }; _panResponder = PanResponder.create({ onMoveShouldSetPanResponderCapture: () => true, onPanResponderStart: () => this.onStart(), onPanResponderMove: (_event, gestureState) => this.onMove(gestureState), onPanResponderEnd: () => this.onEndMove(), onPanResponderTerminate: () => this.onEndMove() }); onStart() { this.setState({ active: true }); } onMove(gestureState) { const { value } = this.props; const newDeltaValue = this.getValueFromOffset(gestureState.dx); const cappedValue = this.capValueWithinRange(value + newDeltaValue); gestureState.dx = 0; this.setState({ active: true }); this.onSliderValueChanged(cappedValue, true); } onEndMove() { const { value } = this.props; const cappedValue = this.capValueWithinRange(value); this.setState({ active: false }); this.onSliderValueChanged(cappedValue, true); } capValueWithinRange = value => { const { minValue, maxValue } = this.props; const rounded = Math.round(value); if (rounded < minValue) { return minValue; } if (rounded > maxValue) { return maxValue; } return rounded; }; getValueFromOffset = offset => { const { minValue, maxValue } = this.props; if (this.barWidth === undefined) { return 0; } return (maxValue - minValue) * offset / this.barWidth; }; getOffsetFromValue = value => { const { minValue, maxValue } = this.props; if (this.barWidth === undefined) return 0; const valueOffset = value - minValue; const totalRange = maxValue - minValue; const percentage = valueOffset / totalRange; return this.barWidth * percentage; }; onLayout = event => { const { width } = event.nativeEvent.layout; this.barWidth = width; this.forceUpdate(); }; onChangeText = inputValue => { const { minValue, maxValue } = this.props; let value = Number(inputValue); if (Number.isNaN(value)) { value = 0; } if (value < minValue) { value = minValue; } if (value > maxValue) { value = maxValue; } this.onSliderValueChanged(value, false); }; onSliderValueChanged(value, setInputText) { const { onChange } = this.props; if (typeof onChange === 'function') { onChange(value); } if (setInputText) { this.setState({ inputValue: value.toString() }); } } get styles() { const { disabled } = this.props; const { active } = this.state; const currentKnobSize = active ? 20 : 14; return StyleSheet.create({ wrapper: { display: 'flex', flexDirection: 'column' }, sliderOuterWrapper: { flexDirection: 'row', alignItems: 'flex-end' }, sliderWrapper: { height: 48, flex: 1, flexDirection: 'row', alignItems: 'center' }, sliderBar: { position: 'relative', flex: 1, flexDirection: 'row', alignItems: 'center', height: 2, backgroundColor: getColor('borderSubtle00'), marginLeft: 16, marginRight: 16 }, sliderProgress: { height: '100%', backgroundColor: getColor(disabled ? 'borderDisabled' : active ? 'interactive' : 'borderInverse') }, sliderKnob: { position: 'absolute', width: currentKnobSize, height: currentKnobSize, backgroundColor: getColor(disabled ? 'borderDisabled' : active ? 'interactive' : 'iconPrimary'), borderRadius: currentKnobSize / 2, marginLeft: -(currentKnobSize / 2), marginRight: -(currentKnobSize / 2) }, sliderRangeLabel: { color: getColor(disabled ? 'textDisabled' : 'textPrimary') }, textInput: { paddingTop: 0, marginLeft: 16, minWidth: 72 }, label: { color: getColor(disabled ? 'textDisabled' : 'textSecondary') } }); } rangeLabel(value) { const { hideRangeLabels } = this.props; if (hideRangeLabels) { return null; } return /*#__PURE__*/_jsx(Text, { style: this.styles.sliderRangeLabel, type: "code-02", text: value.toString() }); } get slider() { const { value, minValue, maxValue, disabled } = this.props; const cappedValue = this.capValueWithinRange(value); const offset = this.getOffsetFromValue(cappedValue); return /*#__PURE__*/_jsxs(View, { style: this.styles.sliderWrapper, children: [this.rangeLabel(minValue), /*#__PURE__*/_jsxs(View, { style: this.styles.sliderBar, onLayout: this.onLayout, children: [/*#__PURE__*/_jsx(View, { style: [this.styles.sliderProgress, { width: offset }] }), /*#__PURE__*/_jsx(View, { style: [this.styles.sliderKnob, { left: offset }], ...(!disabled ? this._panResponder.panHandlers : {}) })] }), this.rangeLabel(maxValue)] }); } render() { const { label, disabled, hideLabel, hideTextInput, accessibleText, style, value } = this.props; return /*#__PURE__*/_jsxs(View, { style: styleReferenceBreaker(this.styles.wrapper, style), accessibilityLabel: accessibleText || defaultText.slider, accessibilityHint: label, children: [!hideLabel && /*#__PURE__*/_jsx(Text, { style: this.styles.label, type: "label-01", text: label }), /*#__PURE__*/_jsxs(View, { style: this.styles.sliderOuterWrapper, children: [this.slider, !hideTextInput && /*#__PURE__*/_jsx(TextInput, { style: this.styles.textInput, value: String(value), disabled: disabled, onChangeText: this.onChangeText, componentProps: { keyboardType: 'number-pad' } })] })] }); } } //# sourceMappingURL=index.js.map