From a45393c279f1828adc15b2791e1990216bc57348 Mon Sep 17 00:00:00 2001 From: kostasdano Date: Thu, 27 Jul 2023 00:47:32 +0300 Subject: [PATCH] feat: pr comments --- .../NumberField/NumberField.style.ts | 9 + .../NumberField/NumberField.test.tsx | 16 + src/components/NumberField/NumberField.tsx | 87 ++-- .../NumberField.stories.storyshot | 424 +++++++++--------- .../components/Stepper/Stepper.style.ts | 1 + .../components/Stepper/Stepper.tsx | 2 + src/components/TextField/TextField.tsx | 73 +-- src/hooks/useFieldUtils.tsx | 73 +++ 8 files changed, 372 insertions(+), 313 deletions(-) create mode 100644 src/components/NumberField/NumberField.style.ts create mode 100644 src/hooks/useFieldUtils.tsx diff --git a/src/components/NumberField/NumberField.style.ts b/src/components/NumberField/NumberField.style.ts new file mode 100644 index 000000000..e3c910d46 --- /dev/null +++ b/src/components/NumberField/NumberField.style.ts @@ -0,0 +1,9 @@ +import { css, SerializedStyles } from '@emotion/react'; +import { rem } from 'theme/utils'; + +export const groupStyles = (): SerializedStyles => { + return css` + /** @TODO: add tokens instead of rem */ + width: ${`calc(100% - ${rem(44)})`}; + `; +}; diff --git a/src/components/NumberField/NumberField.test.tsx b/src/components/NumberField/NumberField.test.tsx index e1291481f..0845a862e 100644 --- a/src/components/NumberField/NumberField.test.tsx +++ b/src/components/NumberField/NumberField.test.tsx @@ -49,6 +49,22 @@ describe('NumberField', () => { expect(input).toHaveValue('12.00'); }); + it('increases and decreases the number through keyboard', async () => { + renderNumberField({ step: 0.5, hasStepper: true }); + input = screen.getByTestId('input') as HTMLInputElement; + + userEvent.type(input, '12.00'); + userEvent.click(document.body); + + userEvent.click(input); + + userEvent.type(input, '{arrowup}'); + expect(input).toHaveValue('12.50'); + + userEvent.type(input, '{arrowdown}'); + expect(input).toHaveValue('12.00'); + }); + it('it rejects number input outside min and max given', async () => { renderNumberField({ minValue: 10, maxValue: 20 }); input = screen.getByTestId('input') as HTMLInputElement; diff --git a/src/components/NumberField/NumberField.tsx b/src/components/NumberField/NumberField.tsx index 9ec69e440..9b1611fdb 100644 --- a/src/components/NumberField/NumberField.tsx +++ b/src/components/NumberField/NumberField.tsx @@ -1,20 +1,27 @@ -import useCombinedRefs from 'hooks/useCombinedRefs'; -import { useTheme } from 'index'; +import useFieldUtils from 'hooks/useFieldUtils'; import { omit } from 'lodash'; -import React, { useMemo } from 'react'; -import { NumberField as ReactAriaNumberField, Group, Input, } from 'react-aria-components'; +import React from 'react'; +import { NumberField as ReactAriaNumberField, Group, Input } from 'react-aria-components'; import { generateUniqueID } from 'utils/helpers'; import Stepper from './components/Stepper/Stepper'; +import { groupStyles } from './NumberField.style'; import { TextFieldProps } from '../TextField/TextField'; -import { getTextInputBaseTokens } from '../TextInputBase/TextInputBase.tokens'; -import Icon, { AcceptedIconNames } from 'components/Icon'; import Label from 'components/Label'; import { suffixContainerStyle } from 'components/TextField/TextField.style'; import TextInputBase from 'components/TextInputBase/TextInputBase'; import { inputStyle } from 'components/TextInputBase/TextInputBase.style'; -export type NumberFieldProps = Omit & { +export type NumberFieldProps = Omit< + TextFieldProps, + | 'mask' + | 'maskChar' + | 'value' + | 'onChange' + | 'isMulti' + | 'onMultiValueClearAll' + | 'onMultiValueDelete' +> & { /** Callback fired when the `input` is changed. */ onChange?: (value: number) => void; /** The value of the `input` element. */ @@ -52,52 +59,28 @@ const NumberField = React.forwardRef((props, ...rest } = props; - const theme = useTheme(); - const tokens = getTextInputBaseTokens(theme); - - const inputRef = React.useRef(null); - const combinedRefs = useCombinedRefs(inputRef, ref); - - const isLocked = status?.type === 'read-only'; - const hintMessageId = status?.hintMessage ? status?.id ?? `${id}_hintMessage` : undefined; - - const handleClick = () => { - if (!isLocked && !isDisabled) { - combinedRefs.current?.focus(); - } - }; - - const suffixContent = useMemo(() => { - if (isLocked || typeof suffix === 'string') { - const iconName = isLocked ? 'lock' : suffix; - - return ( - - ); - } - - return suffix; - }, [isLocked, suffix, theme.utils]); - - const textInputBaseSx = useMemo( - () => - !suffixContent && !hasStepper - ? { - textField: { - paddingRight: tokens('paddingContentLeft'), - }, - } - : {}, - [hasStepper, suffixContent, tokens] - ); + const { + isLocked, + hintMessageId, + handleContainerClick, + suffixContent, + combinedRefs, + textInputBaseSx, + } = useFieldUtils({ + id, + suffix, + status, + isDisabled, + ref, + }); return ( -
- +
+
((props, minValue={minValue} maxValue={maxValue} > - +