Skip to content

Commit

Permalink
Extracted ValueConverter type
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexShukel committed Sep 12, 2023
1 parent 04922e1 commit 8bc9f27
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
7 changes: 7 additions & 0 deletions packages/x/src/formatInteger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const formatInteger = (value: number | null | undefined) => {
if (typeof value !== 'number' || !Number.isFinite(value)) {
return '';
}

return value.toFixed(0);
};
6 changes: 4 additions & 2 deletions packages/x/src/useConverterField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ export class ConversionError extends Error {
}
}

export type ConverterFieldConfig<T> = {
export type ValueConverter<T> = {
parse: (value: string) => T;
format: (value: T) => string;
} & FieldConfig<T>;
};

export type ConverterFieldConfig<T> = ValueConverter<T> & FieldConfig<T>;

export type ConverterFieldBag<T> = {
text: string;
Expand Down
30 changes: 13 additions & 17 deletions packages/x/src/useIntegerField.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
import { useCallback, useContext } from 'react';
import { FieldConfig, useFieldValidator } from '@reactive-forms/core';

import { formatInteger } from './formatInteger';
import { IntegerFieldI18nContext } from './IntegerFieldI18n';
import { ConversionError, ConverterFieldBag, useConverterField } from './useConverterField';
import { ConversionError, ConverterFieldBag, useConverterField, ValueConverter } from './useConverterField';

const INTEGER_REGEX = /^-?\d+$/;

const formatInteger = (value: number | null | undefined) => {
if (typeof value !== 'number' || !Number.isFinite(value)) {
return '';
}

return value.toFixed(0);
};

export type IntegerFieldConfig = FieldConfig<number | null | undefined> & {
required?: boolean;
min?: number;
max?: number;

formatValue?: (value: number | null | undefined) => string;
};
} & Partial<ValueConverter<number | null | undefined>>;

export type IntegerFieldBag = ConverterFieldBag<number | null | undefined>;

Expand All @@ -31,12 +22,17 @@ export const useIntegerField = ({
required,
min,
max,
formatValue = formatInteger,
parse: customParse,
format = formatInteger,
}: IntegerFieldConfig): IntegerFieldBag => {
const i18n = useContext(IntegerFieldI18nContext);

const parseInteger = useCallback(
const parse = useCallback(
(text: string) => {
if (customParse) {
return customParse(text);
}

text = text.trim();

if (text.length === 0) {
Expand All @@ -55,12 +51,12 @@ export const useIntegerField = ({

return value;
},
[i18n.invalidInput],
[customParse, i18n.invalidInput],
);

const integerBag = useConverterField({
parse: parseInteger,
format: formatValue,
parse,
format,
name,
validator,
schema,
Expand Down
20 changes: 17 additions & 3 deletions packages/x/tests/useIntegerField.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,25 @@ describe('Integer field', () => {
});

it('Should be able to format integer differently', () => {
const formatValue = jest.fn(() => 'custom');
const format = jest.fn(() => 'custom');
const initialValue = 42;
const [{ result }] = renderUseIntegerField({ formatValue, initialValue });
const [{ result }] = renderUseIntegerField({ format, initialValue });

expect(result.current.text).toBe('custom');
expect(formatValue).toBeCalledWith(initialValue);
expect(format).toBeCalledWith(initialValue);
});

it('Should call custom parse function', async () => {
const parse = jest.fn();

const [{ result }] = renderUseIntegerField({ parse });

await act(() => {
result.current.onTextChange('0');
});

await waitFor(() => {
expect(parse).toBeCalledWith('0');
});
});
});

0 comments on commit 8bc9f27

Please sign in to comment.