Skip to content

InputMask

WARNING

InputMask is deprecated and will be removed in the next major release.

Mask

This is an example of a basic input with a mask feature. The mask is defined using the mask property, which specifies the input format and validates the entered value.

TIP

Remember to set a placeholder for the input field. The placeholder should match the mask.

tsx
import { Flex } from '@semcore/ui/base-components';
import InputMask from '@semcore/ui/input-mask';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = () => {
  return (
    <Flex direction='column' gap={2} w={224}>
      <Text tag='label' htmlFor='basic-example' size={200}>
        Card number
      </Text>
      <InputMask w={224}>
        <InputMask.Value
          mask='9999 9999 9999 9999'
          placeholder='____ ____ ____ ____'
          id='basic-example'
          aria-describedby='basic-example-hint'
          autoComplete='cc-number'
        />
      </InputMask>
      <Text size={100} color='gray-500' id='basic-example-hint'>
        Please enter the 16-digit number of your debit card.
      </Text>
    </Flex>
  );
};

export default Demo;

Aliases

aliases is the object that defines how characters in the mask are validated. By default, they are configured as follows:

  • 9 - numbers
  • a - Latin and Cyrillic letters in any case
  • * - numbers and Latin and Cyrillic letters in any case
tsx
import { Flex } from '@semcore/ui/base-components';
import InputMask from '@semcore/ui/input-mask';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = () => {
  const [value, setValue] = React.useState('99');

  return (
    <Flex direction='column' gap={2} w={224}>
      <Text tag='label' htmlFor='aliases-example' size={200}>
        Item index
      </Text>
      <InputMask w={224}>
        <InputMask.Value
          id='aliases-example'
          aliases={{ x: /[0-9]/ }}
          mask='99xxxx'
          value={value}
          onChange={setValue}
          aria-describedby='aliases-example-hint'
        />
      </InputMask>
      <Text size={100} color='gray-500' id='aliases-example-hint'>
        Enter any 4 digits
      </Text>
    </Flex>
  );
};

export default Demo;

Pipe

pipe is a function that processes and changes the InputMask value after user input.

In the example below, it is used for formatting and validating the card's expire date input. The focus is switched to the next input by the onSucces event. It is called when the entered value fully matches the input mask.

tsx
import { Box, Flex } from '@semcore/ui/base-components';
import InputMask from '@semcore/ui/input-mask';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = () => {
  const expireDateInput = React.useRef<HTMLInputElement>(null);
  const handleSuccess = React.useCallback(() => expireDateInput.current?.focus(), []);

  return (
    <Flex
      direction='column'
      wMax={300}
      gap={2}
      p={8}
      mx='auto'
      style={{
        borderRadius: 'var(--intergalactic-surface-rounded)',
        background: 'var(--intergalactic-bg-secondary-neutral)',
      }}
    >
      <Text tag='label' size={300} htmlFor='card_number'>
        Card number
      </Text>
      <InputMask size='l' mb={2}>
        <InputMask.Value
          mask='9999 9999 9999 9999'
          placeholder='____ ____ ____ ____'
          onSuccess={handleSuccess}
          title='16 digits'
          id='card_number'
          autoComplete='cc-number'
        />
      </InputMask>
      <Flex alignItems='center' justifyContent='flex-end' gap={2}>
        <Text tag='label' size={300} htmlFor='expire_date'>
          Expiry date
        </Text>
        <InputMask size='l' wMax={85}>
          <InputMask.Value
            ref={expireDateInput}
            mask='99/99'
            placeholder='MM/YY'
            pipe={pipeExpireDate}
            title='Month and year, 4 digits in total'
            id='expire_date'
            autoComplete='cc-exp'
          />
        </InputMask>
      </Flex>
    </Flex>
  );
};

const pipeExpireDate = (maskedValue: string, conf: { rawValue: string }) => {
  let value = maskedValue;

  if (conf.rawValue.length === 7) {
    value = conf.rawValue
      .split('/')
      .map((valueItem, index) => {
        if (valueItem.length === 2) {
          return valueItem;
        }

        if (valueItem.length === 4 && index === 1) {
          return valueItem.toString().substring(2);
        }
      })
      .join('/');
  }

  const indexesOfPipedChars = [];
  const firstMonthDigit = Number.parseInt(value[0], 10);
  if (firstMonthDigit > 1) {
    value = `0${value[0]}/${value.split('/')[1]}`;
    indexesOfPipedChars.push(0);
  }
  const [month, year] = value
    .split('/')
    .map((chunk) => (chunk.includes('_') ? undefined : Number.parseInt(chunk, 10)));
  const currentYear = new Date().getFullYear() % 100;
  const currentMonth = new Date().getMonth() + 1;
  if (month === undefined || year === undefined) return false;
  if (month > 12) return false;
  if (year === currentYear && month < currentMonth) return false;
  if (year < currentYear) return false;

  return { value, indexesOfPipedChars };
};

export default Demo;

Released under the MIT License.

Released under the MIT License.