Skip to content

Commit

Permalink
fix(Field.Currency): set limit of safe big number
Browse files Browse the repository at this point in the history
Fixes #3124
  • Loading branch information
tujoworker committed Jan 7, 2024
1 parent 2ca216a commit 3fb9007
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.
| `percent` | `boolean` | _(optional)_ Format a number as percentage. |
| `prefix` | `string` | _(optional)_ Text added before the value input. |
| `suffix` | `string` | _(optional)_ Text added after the value input. |
| `minimum` | `number` | _(optional)_ Validation for inclusive minimum number value (greater than or equal). |
| `maximum` | `number` | _(optional)_ Validation for inclusive maximum number value (less than or equal). |
| `minimum` | `number` | _(optional)_ Validation for inclusive minimum number value (greater than or equal). Defaults to `-Number.MAX_SAFE_INTEGER`. |
| `maximum` | `number` | _(optional)_ Validation for inclusive maximum number value (less than or equal). Defaults to `Number.MAX_SAFE_INTEGER`. |
| `exclusiveMinimum` | `number` | _(optional)_ Validation for exclusive minimum number value (greater than). |
| `exclusiveMaximum` | `number` | _(optional)_ Validation for exclusive maximum number value (less than). |
| `multipleOf` | `number` | _(optional)_ Validation that requires the number to be a multiple of given value. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,16 @@ The transformers are hooks to transform the value on different stages.

They should return a transformed value: `(value) => value`

- `toInput` transforms the value before it gets returned by the hook:
- `toInput` transforms the value before it gets returned as the `value`:

```ts
const { value } = useDataValue(props)
```

- `fromInput` transforms the value given by `handleChange` before it is used in the further process flow.

```ts
handleChange(value)
```
- `fromInput` transforms the value given by `handleChange` before it is used in the further process flow. Use it to destruct the value form the original event object.

- `toEvent` transforms the internal value before it gets returned by even callbacks such as `onChange`, `onFocus` and `onBlur`.

- `fromExternal` transforms the given props `value` before any other step gets entered.

- `transformValue` transforms the value given by `handleChange` after `fromInput` and before `updateValue` and `toEvent`.

#### Additional features

| Property | Type | Description |
Expand Down
29 changes: 24 additions & 5 deletions packages/dnb-eufemia/src/extensions/forms/Field/Number/Number.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,32 @@ function NumberComponent(props: Props) {
return external
}, [])
const fromInput = useCallback(
({ value, numberValue }: { value: string; numberValue: number }) => {
if (value === '') {
(event: { value?: string; numberValue: number }) => {
if (typeof event === 'number') {
event = { numberValue: event }
}

if (event?.value === '') {
return props.emptyValue
}
return numberValue

return event?.numberValue
},
[props.emptyValue]
)
const transformValue = useCallback(
(value: number, currentValue: number) => {
if (
value > Number.MAX_SAFE_INTEGER ||
value < -Number.MAX_SAFE_INTEGER
) {
return currentValue
}

return value
},
[]
)

const maskProps: Partial<InputMaskedProps> = useMemo(() => {
if (currency) {
Expand Down Expand Up @@ -155,6 +173,7 @@ function NumberComponent(props: Props) {
schema,
toInput,
fromInput,
transformValue,
size:
props.size !== 'small' && props.size !== 'large'
? 'medium'
Expand All @@ -174,8 +193,8 @@ function NumberComponent(props: Props) {
labelDescription,
labelSecondary,
value,
minimum,
maximum,
minimum = -Number.MAX_SAFE_INTEGER,
maximum = Number.MAX_SAFE_INTEGER,
disabled,
info,
warning,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,42 @@ describe('Field.Number', () => {
expect(screen.getByLabelText('Number label')).toBeInTheDocument()
})

it('corrects minimum number', () => {
render(<Field.Number value={-Number.MAX_SAFE_INTEGER} />)

const input = document.querySelector('input')

fireEvent.change(input, {
target: {
value: String(-Number.MAX_SAFE_INTEGER - 1),
},
})

expect(input).toHaveValue(String(-Number.MAX_SAFE_INTEGER - 1))

fireEvent.blur(input)

expect(input).toHaveValue(String(-Number.MAX_SAFE_INTEGER))
})

it('corrects maximum number', () => {
render(<Field.Number value={Number.MAX_SAFE_INTEGER} />)

const input = document.querySelector('input')

fireEvent.change(input, {
target: {
value: String(Number.MAX_SAFE_INTEGER + 1),
},
})

expect(input).toHaveValue(String(Number.MAX_SAFE_INTEGER + 1))

fireEvent.blur(input)

expect(input).toHaveValue(String(Number.MAX_SAFE_INTEGER))
})

it('should support disabled prop', () => {
const { rerender } = render(
<Field.Number label="Disabled label" disabled />
Expand Down
10 changes: 9 additions & 1 deletion packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default function useDataValue<
toInput = (value: Value) => value,
fromInput = (value: Value) => value,
toEvent = (value: Value) => value,
transformValue = (value: Value) => value,
fromExternal = (value: Value) => value,
validateRequired = (value: Value, { emptyValue, required }) => {
const res =
Expand All @@ -85,6 +86,7 @@ export default function useDataValue<
fromInput,
toEvent,
fromExternal,
transformValue,
validateRequired,
})

Expand Down Expand Up @@ -484,9 +486,10 @@ export default function useDataValue<
argFromInput: Value,
additionalArgs: AdditionalEventArgs = undefined
) => {
const currentValue = valueRef.current
let newValue = transformers.current.fromInput(argFromInput)

if (newValue === valueRef.current) {
if (newValue === currentValue) {
// Avoid triggering a change if the value was not actually changed. This may be caused by rendering components
// calling onChange even if the actual value did not change.
return
Expand All @@ -496,6 +499,11 @@ export default function useDataValue<
newValue = toCapitalized(String(newValue || '')) as Value
}

newValue = transformers.current.transformValue(
newValue,
currentValue
)

updateValue(newValue)

changedRef.current = true
Expand Down
11 changes: 6 additions & 5 deletions packages/dnb-eufemia/src/extensions/forms/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,13 @@ export interface FieldProps<
continuousValidation?: boolean
errorMessages?: ErrorMessages
// Derivatives
toInput?: (external: Value | undefined) => any
fromInput?: (...args: any[]) => Value | undefined
toEvent?: (internal: Value | undefined) => any
fromExternal?: (...args: any[]) => Value | undefined
toInput?: (external: Value | unknown) => Value | unknown
fromInput?: (external: Value | unknown) => Value
toEvent?: (internal: Value) => Value
fromExternal?: (external: Value) => Value
transformValue?: (value: Value, currentValue: Value) => Value
validateRequired?: (
internal: Value | undefined,
internal: Value,
{
emptyValue,
required,
Expand Down

0 comments on commit 3fb9007

Please sign in to comment.