diff --git a/packages/shared/src/forms/SliderLabels.js b/packages/shared/src/forms/SliderLabels.js index eba40788..d2bd961f 100644 --- a/packages/shared/src/forms/SliderLabels.js +++ b/packages/shared/src/forms/SliderLabels.js @@ -9,7 +9,6 @@ import Text from '../Text'; import StyleSheet from '../PlatformStyleSheet'; import Price from '../Price'; import type { TranslationType } from '../../types/Translation'; -import useCalculateSliderPositions from './useCalculateSliderPositions'; type Props = {| +startLabel: TranslationType | React.Element, @@ -20,30 +19,38 @@ type Props = {| +min: number, |}; +const LABEL_MARGIN = parseInt(defaultTokens.spaceXSmall, 10); + export default function SliderLabels(props: Props) { const [width, setWidth] = React.useState(0); const [labelStartWidth, setLabelStartWidth] = React.useState(0); - const [labelStartAtMax, setLabelStartAtMax] = React.useState(false); const [labelEndWidth, setLabelEndWidth] = React.useState(0); const [paddingLeft, setPaddingLeft] = React.useState(0); const [paddingRight, setPaddingRight] = React.useState(0); - useCalculateSliderPositions({ - labelEndWidth, - labelStartAtMax, - labelStartWidth, - paddingLeft, - paddingRight, - props, - width, - setPaddingLeft, - setLabelStartAtMax, - setPaddingRight, - min: props.min, - max: props.max, - endValue: props.endValue, - startValue: props.startValue, - }); + React.useEffect(() => { + const maxOffsetLeft = + width - labelStartWidth - labelEndWidth - LABEL_MARGIN + paddingRight; + const offsetLeft = Math.max( + (props.startValue / props.max) * width - labelStartWidth / 2, + 0, + ); + setPaddingLeft(Math.min(maxOffsetLeft, offsetLeft)); + }, [props.startValue, labelStartWidth]); // eslint-disable-line react-hooks/exhaustive-deps + + React.useEffect(() => { + if (props.endValue != null) { + const maxOffsetRight = + (width - labelEndWidth - labelStartWidth - LABEL_MARGIN - paddingLeft) * + -1; + const offsetRight = Math.min( + (props.endValue / props.max) * width - width + labelEndWidth / 2, + 0, + ); + + setPaddingRight(Math.max(maxOffsetRight, offsetRight)); + } + }, [props.endValue, labelEndWidth]); // eslint-disable-line react-hooks/exhaustive-deps function saveFullWidth(e: OnLayout) { setWidth(Math.floor(e.nativeEvent.layout.width)); @@ -59,14 +66,14 @@ export default function SliderLabels(props: Props) { return ( @@ -76,7 +83,7 @@ export default function SliderLabels(props: Props) { @@ -95,9 +102,6 @@ const styles = StyleSheet.create({ marginBottom: 5, justifyContent: 'space-between', }, - sliderLabelsEnd: { - justifyContent: 'flex-end', - }, label: { fontSize: 14, color: defaultTokens.paletteBlueNormal, diff --git a/packages/shared/src/forms/__tests__/SliderLabels.test.js b/packages/shared/src/forms/__tests__/SliderLabels.test.js index fa394c3e..a73f2436 100644 --- a/packages/shared/src/forms/__tests__/SliderLabels.test.js +++ b/packages/shared/src/forms/__tests__/SliderLabels.test.js @@ -61,14 +61,14 @@ it('should have startValue in the middle', () => { }); expect(startLabel.props.style).toMatchInlineSnapshot(` - Object { - "transform": Array [ Object { - "translateX": 365, - }, - ], - } - `); + "transform": Array [ + Object { + "translateX": 290, + }, + ], + } + `); }); it('should display the label at the end', () => { @@ -95,7 +95,15 @@ it('should display the label at the end', () => { startLabel.props.onLayout({ nativeEvent: { layout: { width: 20 } } }); }); - expect(viewContainer.props.style[1].justifyContent).toBe('flex-end'); + expect(startLabel.props.style).toMatchInlineSnapshot(` + Object { + "transform": Array [ + Object { + "translateX": 472, + }, + ], + } + `); }); it('should have translateX on both labels', () => { @@ -130,7 +138,7 @@ it('should have translateX on both labels', () => { Object { "transform": Array [ Object { - "translateX": 201, + "translateX": 190, }, ], } @@ -139,7 +147,7 @@ it('should have translateX on both labels', () => { Object { "transform": Array [ Object { - "translateX": -69, + "translateX": -90, }, ], } @@ -175,5 +183,5 @@ it('should have no translateX', () => { }); expect(startLabel.props.style.transform[0].translateX).toBe(0); - expect(endLabel.props.style.transform[0].translateX).toBe(-0); + expect(endLabel.props.style.transform[0].translateX).toBe(0); }); diff --git a/packages/shared/src/forms/__tests__/__snapshots__/SliderLabels.test.js.snap b/packages/shared/src/forms/__tests__/__snapshots__/SliderLabels.test.js.snap index 23e75023..a181ed45 100644 --- a/packages/shared/src/forms/__tests__/__snapshots__/SliderLabels.test.js.snap +++ b/packages/shared/src/forms/__tests__/__snapshots__/SliderLabels.test.js.snap @@ -4,16 +4,13 @@ exports[`renders with one label 1`] = ` @@ -50,16 +47,13 @@ exports[`renders with two labels 1`] = ` @@ -95,7 +89,7 @@ exports[`renders with two labels 1`] = ` Object { "transform": Array [ Object { - "translateX": -0, + "translateX": 0, }, ], } diff --git a/packages/shared/src/forms/useCalculateSliderPositions.js b/packages/shared/src/forms/useCalculateSliderPositions.js deleted file mode 100644 index 760951b0..00000000 --- a/packages/shared/src/forms/useCalculateSliderPositions.js +++ /dev/null @@ -1,140 +0,0 @@ -// @flow - -import * as React from 'react'; - -type Props = {| - +labelEndWidth: number, - +labelStartAtMax: boolean, - +labelStartWidth: number, - +paddingLeft: number, - +paddingRight: number, - +props: any, - +width: number, - +setPaddingLeft: number => void, - +setLabelStartAtMax: boolean => void, - +setPaddingRight: number => void, - +min: number, - +max: number, - +endValue: ?number, - +startValue: number, -|}; - -export default function useCalculateSliderPositions({ - labelEndWidth, - labelStartAtMax, - labelStartWidth, - paddingLeft, - paddingRight, - props, - width, - setPaddingLeft, - setLabelStartAtMax, - setPaddingRight, - min, - max, - endValue, - startValue, -}: Props) { - React.useEffect(() => { - function getOffset(input: number) { - let val; - - if (input > max) { - val = max; - } else if (input < min) { - val = min; - } else { - val = input; - } - return Math.round((val / (max - min)) * width); - } - - function calculateMarkerEndOffset(): number { - if (!endValue) { - return 0; - } - - const offset = getOffset(endValue); - return Math.round(width - offset); - } - - function calculateMarkerStartOffset(): number { - return getOffset(startValue); - } - - function isBelowMaxPadding(value: number, gap: number = 0): boolean { - const maxPadding = getMaxPadding(gap); - return value + gap < maxPadding; - } - - function setPaddingForOneLabel(): void { - const startLabelOffset = getStartLabelOffset(); - const hasOffsetChanged = paddingLeft !== startLabelOffset; - - if (isBelowMaxPadding(startLabelOffset)) { - if (hasOffsetChanged) { - setPaddingLeft(startLabelOffset); - } - - if (labelStartAtMax) { - setLabelStartAtMax(false); - } - } else if (labelStartAtMax === false) { - setLabelStartAtMax(true); - } - } - - function getMaxPadding(gap: number): number { - return Math.floor(width - labelStartWidth - labelEndWidth - gap); - } - - function getStartLabelOffset(): number { - const startMarkerOffset = calculateMarkerStartOffset(); - const startLabelHalf = labelStartWidth / 2; - - return startMarkerOffset < startLabelHalf - ? 0 - : startMarkerOffset - startLabelHalf; - } - - function setPaddingForTwoLabels(): void { - const startLabelOffset = getStartLabelOffset(); - const endMarkerOffset = calculateMarkerEndOffset(); - const endLabelHalf = labelEndWidth / 2; - const endLabelOffset = - endMarkerOffset < endLabelHalf ? 0 : endMarkerOffset - endLabelHalf; - - const hasOffsetChanged = - paddingLeft !== startLabelOffset || paddingRight !== endLabelOffset; - - if ( - isBelowMaxPadding(startLabelOffset + endLabelOffset, 10) && - hasOffsetChanged - ) { - setPaddingLeft(startLabelOffset); - setPaddingRight(endLabelOffset); - } - } - - if (props.endValue) { - setPaddingForTwoLabels(); - } else { - setPaddingForOneLabel(); - } - }, [ - endValue, - labelEndWidth, - labelStartAtMax, - labelStartWidth, - max, - min, - paddingLeft, - paddingRight, - props, - setLabelStartAtMax, - setPaddingLeft, - setPaddingRight, - startValue, - width, - ]); -}