Import
import { InputMasked } from '@dnb/eufemia'
Description
The InputMasked component uses the basic Input component, but with input masking powered by Maskito.
Relevant links
How it works
This component uses the basic Input component with a set of additional options and features.
You can either create your own mask using an array of RegExp and string tokens, a single RegExp, or use one of the provided number/currency masks. There are also masks that change based on different locales (asCurrency or asNumber).
Array masks define the expected input character-by-character. Each RegExp in the array represents a user-editable slot, while strings act as fixed separator tokens. For example, [/[0-9]/, /[0-9]/, ' ', /[0-9]/, /[0-9]/, ' ', /[0-9]/, /[0-9]/] creates a mask for a six-digit code with spaces after every two digits.
You can also use allowOverflow to let users type beyond the defined mask length, and overwriteMode to control how characters are overwritten (shift moves to the next slot, replace stays on the current slot).
Accessibility
Screen readers will also read the mask before the user enters the content. Additionally, the user will hear the mask during typing. This behavior can have both positive and negative side effects for the user, but overall, it works well.
Entering either a comma or a dot will act as a decimal separator if decimals are enabled and one of the internal masks for numbers is used.
Note: When pasting values that contain a dot (.) in a locale where the dot is not the native decimal or thousands separator (e.g. Norwegian), the component uses a heuristic to disambiguate: a dot followed by exactly three digits is treated as a thousands separator and removed, while any other dot is treated as a decimal separator. For example, pasting 20.500 in Norwegian locale produces 20 500 (twenty thousand five hundred), while pasting 20.5 produces 20,5 (twenty point five). Values with a leading zero (e.g. 0.500) are always treated as decimals. Be aware that a dot-decimal value with exactly three fractional digits (e.g. 2.000 meaning 2.0) will be interpreted as thousands (2 000) — this is an inherent limitation of the heuristic. Commas are only treated as thousands separators when multiple comma-separated groups appear (e.g. 1,234,567); a single trailing ,### is kept as a decimal. When both dots and commas are present (e.g. 1,234.56 or 1.234,56), the rightmost separator is always treated as the decimal and the others as thousands separators.
InputMode
NB: Please do not set inputMode="numeric" or inputMode="decimal" because devices may or may not show a minus key (-)!
The InputMasked component handles soft keyboards (iOS and Android) by using either inputMode="numeric" or inputMode="decimal", depending on allowNegative and allowDecimal (getSoftKeyboardAttributes).
For iOS, it additionally sets type="number" during focus (InputModeNumber). This way, the correct numeric soft keyboard is shown.
Mask based on locale
The InputMasked component supports masks based on a given locale. The locale will be inherited from the Eufemia Provider if not specified.
You can enable these masks by setting:
asCurrency="EUR"asNumber={true}
You can still provide custom mask parameters to currencyMask={{ ... }} or numberMask={{ ... }}. Alternatively, you can use maskOptions={{ ... }} and provide your extra options there.
More details in the examples above.
Clean number values
If you use asCurrency or asNumber, you must always provide a clean number without any mask (value="1234.50"):
You can also receive a clean number value you can use and pass back in:
Decimals
numberMaskwill default to no decimalscurrencyMaskwill default to no decimalsasNumberwill default to no decimalsasCurrencywill default to 2 decimals
You can change the number of decimals by sending in options to the currencyMask, numberMask, or maskOptions (see example above).
This example also shows how to affect every InputMasked component in your application by setting these options on the Eufemia Provider.
To remove a decimal limit, you can provide null and allow decimals with allowDecimal:
Demos
Locale based numbers
When you use asNumber or asPercent (and asCurrency see below) it will create a mask for you and inherit the locale from the Eufemia Provider, if the locale property is not given.
You can still define extra mask parameters with numberMask or maskOptions, as the second input example shows (e.g. decimalLimit).
<Flex.Vertical> <InputMasked label="Number" asNumber maskOptions={{ allowNegative: false, }} value="1234.50" onChange={({ numberValue }) => { console.log(numberValue) }} /> <InputMasked label="Number (decimal limit)" asNumber numberMask={{ decimalLimit: 2, }} value="1234.016" onChange={({ numberValue }) => { console.log(numberValue) }} /> <InputMasked label="Percentage" asPercent numberMask={{ decimalLimit: 1, }} value="1234.016" onChange={({ numberValue }) => { console.log(numberValue) }} /> </Flex.Vertical>
Locale based asCurrency
When you use asCurrency it will create a mask for you and inherit the locale from the Eufemia Provider, if the locale property is not given.
<Flex.Vertical> <InputMasked label="Currency" asCurrency="EUR" value="1234.50" onChange={({ numberValue }) => { console.log(numberValue) }} /> <Provider locale="en-GB" InputMasked={{ currencyMask: { decimalLimit: 3, }, }} > <InputMasked label="Currency" asCurrency="USD" value="1234.567" onChange={({ numberValue }) => { console.log(numberValue) }} /> </Provider> </Flex.Vertical>
Define the currencyMask manually
<Flex.Vertical> <InputMasked label="Left aligned (default)" showMask currencyMask="kr" onChange={({ numberValue }) => { console.log(numberValue) }} /> <InputMasked label="Right aligned" showMask currencyMask={{ currency: 'NOK', }} align="right" onChange={({ numberValue }) => { console.log(numberValue) }} /> </Flex.Vertical>
Customize the number mask
<InputMasked label="Masked amount" showMask numberMask={{ suffix: ' kr', allowDecimal: true, }} onChange={({ numberValue }) => { console.log(numberValue) }} />
Using the numberMask with a combined suffix
<InputMasked label="Masked input" value="1000000" numberMask={{ suffix: ',-', allowDecimal: false, }} suffix="kr" onChange={({ numberValue }) => { console.log(numberValue) }} />
Using the numberMask and a prefix
<InputMasked label="Masked input" numberMask={{ prefix: 'NOK ', }} stretch={true} placeholder="Enter a number" onChange={({ numberValue }) => { console.log(numberValue) }} />