diff --git a/.changeset/warm-ants-collect.md b/.changeset/warm-ants-collect.md new file mode 100644 index 000000000..fa7f8b4a7 --- /dev/null +++ b/.changeset/warm-ants-collect.md @@ -0,0 +1,7 @@ +--- +'hostd': minor +'renterd': minor +'@siafoundation/design-system': minor +--- + +Fixed an issue where number fields would not properly handle user input starting with a decimal separator. diff --git a/libs/design-system/src/core/BaseNumberField.tsx b/libs/design-system/src/core/BaseNumberField.tsx index 27c0fdf70..e75852faa 100644 --- a/libs/design-system/src/core/BaseNumberField.tsx +++ b/libs/design-system/src/core/BaseNumberField.tsx @@ -58,6 +58,18 @@ export function BaseNumberField({ autoComplete="off" spellCheck={false} onValueChange={onValueChange} + transformRawValue={(value) => { + if (value.length > 0) { + if (value[0] === '.') { + return '0.' + value.slice(1) + } + if (value[0] === ',') { + return '0,' + value.slice(1) + } + } + + return value + }} className={cx( textFieldStyles({ variant, diff --git a/libs/design-system/src/core/NumberField.spec.tsx b/libs/design-system/src/core/NumberField.spec.tsx index 21319f021..ef41833ef 100644 --- a/libs/design-system/src/core/NumberField.spec.tsx +++ b/libs/design-system/src/core/NumberField.spec.tsx @@ -46,6 +46,39 @@ describe('NumberField', () => { expectOnChangeValues([undefined, '4', '44', '44', '444', '444'], onChange) }) + it('updates value starting with decimal', async () => { + const user = userEvent.setup() + const onChange = jest.fn() + const { input } = await renderNode({ + initialValue: new BigNumber(33), + onChange, + }) + + expect(input.value).toBe('33') + await user.click(input) + await user.clear(input) + await user.type(input, '.44') + fireEvent.blur(input) + expect(input.value).toBe('0.44') + }) + + it('updates value starting with comma decimal separator', async () => { + const user = userEvent.setup() + const onChange = jest.fn() + const { input } = await renderNode({ + initialValue: new BigNumber(33), + locale: 'de-DE', + onChange, + }) + + expect(input.value).toBe('33') + await user.click(input) + await user.clear(input) + await user.type(input, ',44') + fireEvent.blur(input) + expect(input.value).toBe('0,44') + }) + it('works with alternate locale: DE', async () => { const user = userEvent.setup() const onChange = jest.fn() diff --git a/libs/design-system/src/core/SiacoinField.spec.tsx b/libs/design-system/src/core/SiacoinField.spec.tsx index d3854af07..33b885c9b 100644 --- a/libs/design-system/src/core/SiacoinField.spec.tsx +++ b/libs/design-system/src/core/SiacoinField.spec.tsx @@ -64,6 +64,45 @@ describe('SiacoinField', () => { expectOnChangeValues([undefined, '4', '44', '44', '444', '444'], onChange) }) + it('updates value starting with decimal', async () => { + siaCentralExchangeRateEndpoint('1') + const user = userEvent.setup() + const onChange = jest.fn() + const { scInput, fiatInput } = await renderNode({ + sc: new BigNumber(33), + onChange, + }) + + expect(scInput.value).toBe('33') + expect(fiatInput.value).toBe('$33') + await user.click(scInput) + await user.clear(scInput) + await user.type(scInput, '.44') + fireEvent.blur(scInput) + expect(scInput.value).toBe('0.44') + expect(fiatInput.value).toBe('$0.44') + }) + + it('updates value starting with comma decimal separator', async () => { + siaCentralExchangeRateEndpoint('1') + const user = userEvent.setup() + const onChange = jest.fn() + const { scInput, fiatInput } = await renderNode({ + sc: new BigNumber(33), + locale: 'de-DE', + onChange, + }) + + expect(scInput.value).toBe('33') + expect(fiatInput.value).toBe('$33') + await user.click(scInput) + await user.clear(scInput) + await user.type(scInput, ',44') + fireEvent.blur(scInput) + expect(scInput.value).toBe('0,44') + expect(fiatInput.value).toBe('$0,44') + }) + it('works with alternate locale: DE', async () => { siaCentralExchangeRateEndpoint('1') const user = userEvent.setup() diff --git a/libs/react-core/src/useAppSettings/useIsAuthenticatedRoute.ts b/libs/react-core/src/useAppSettings/useIsAuthenticatedRoute.ts index dce44410b..fc560e1c3 100644 --- a/libs/react-core/src/useAppSettings/useIsAuthenticatedRoute.ts +++ b/libs/react-core/src/useAppSettings/useIsAuthenticatedRoute.ts @@ -1,12 +1,12 @@ 'use client' -import { useRouter } from 'next/router' +import { usePathname } from 'next/navigation' type UnauthenticatedRoutes = { login: string } export function useIsAuthenticatedRoute(routes: UnauthenticatedRoutes) { - const router = useRouter() - return ![routes.login].includes(router.asPath) + const pathname = usePathname() + return ![routes.login].includes(pathname) }