import { Meta, ArgTypes, Canvas } from "@storybook/addon-docs/blocks";
import * as MaskedFieldStories from "./MaskedField.stories";
import { MaskedField } from "./MaskedField";

<Meta of={MaskedFieldStories} />

# MaskedField

The `MaskedField` component is a form input field that automatically formats user input to match supplied patterns. It supports e.g. phone number formatting, comma-separated numbers, and custom mask patterns to ensure consistent data entry.

## Install

```bash
yarn add @simplybusiness/mobius
```

## Usage

```js
import { MaskedField } from "@simplybusiness/mobius";
```

### Phone Number

<Canvas of={MaskedFieldStories.PhoneNumber} />

### Comma Separated Number

<Canvas of={MaskedFieldStories.CommaSeparatedNumber} />

## Props

The `MaskedField` component accepts all props from the `TextField` component, plus the following specific props:

### `mask` (required)

**Type:** `ReactMaskOpts` (from react-imask)

The mask configuration that defines how the input should be formatted. This can be:

- **String pattern**: A string using placeholders like `(000) 000-0000` for phone numbers
- **RegExp**: A regular expression pattern
- **Function**: A custom masking function
- **Number**: For numeric inputs with formatting options
- **Date**: For date inputs
- **Object**: Configuration object with mask options

For comprehensive documentation on mask configuration options, see the [IMask.js guide](https://imask.js.org/guide.html).

#### Number Masks

Number masks are used for formatting numeric inputs with various options for decimal places, thousands separators, and value constraints.

**Basic Example:**
```js
const numberMask = {
  mask: Number,
  thousandsSeparator: ",",
  scale: 0, // Number of decimal places
  signed: false // Allow negative numbers
};
```

**Advanced Example:**
```js
const advancedNumberMask = {
  mask: Number,
  scale: 2, // digits after point, 0 for integers
  thousandsSeparator: ',', // any single char
  padFractionalZeros: false, // if true, pads zeros at end to the length of scale
  normalizeZeros: true, // appends or removes zeros at ends
  radix: '.', // fractional delimiter
  mapToRadix: ['.'], // symbols to process as radix
  min: -10000, // minimum value
  max: 10000, // maximum value
  autofix: true // automatically fix values that exceed min/max
};
```

**Available Options:**
- **`scale`** (number): Digits after the decimal point (0 for integers only)
- **`thousandsSeparator`** (string): Character to use as thousands separator (e.g., ',' or ' ')
- **`padFractionalZeros`** (boolean): If true, pads zeros at the end to match the scale length
- **`normalizeZeros`** (boolean): Appends or removes zeros at the beginning/end
- **`radix`** (string): Character used as decimal separator (e.g., '.' or ',')
- **`mapToRadix`** (array): Array of characters that should be treated as the radix
- **`min`** (number): Minimum allowed value
- **`max`** (number): Maximum allowed value
- **`autofix`** (boolean): Automatically fix values that exceed min/max bounds
- **`signed`** (boolean): Allow negative numbers

For more number masking options, see: https://imask.js.org/guide.html#masked-number

#### Pattern Masks

Pattern masks use special characters to define input structure with placeholders and custom definitions.

**Basic Example:**
```js
const phoneNumberMask = {
  mask: "(000) 000-0000"
};
```

**Custom Definitions Example:**
```js
const customMask = {
  mask: "AA-0000", // A = letter, 0 = digit
  definitions: {
    'A': /[A-Z]/,
    '0': /\d/
  }
};
```

**Advanced Pattern Example:**
```js
const patternMaskWithPlaceholder = {
  mask: '+{7}(000)000-00-00',
  lazy: false, // make placeholder always visible
  placeholderChar: '#' // defaults to '_'
};
```

**Secure Input Example:**
```js
const secureMask = {
  mask: '000000',
  displayChar: '#', // character to display for entered digits
  lazy: false,
  overwrite: 'shift'
};
```

**Built-in Definitions:**
- **`0`** - any digit
- **`a`** - any letter  
- **`*`** - any character
- **`[]`** - make input optional (e.g., `000[000]` makes last 3 digits optional)
- **`{}`** - include fixed part in unmasked value
- **`` ` ``** - prevent symbols from shifting back
- **`\\`** - escape character to treat definition chars as fixed (e.g., `\\0` for literal "0")

**Configuration Options:**
- **`definitions`** (object): Custom character definitions (e.g., `{ '#': /[1-6]/ }`)
- **`lazy`** (boolean): When false, shows placeholder immediately; when true, shows on focus
- **`placeholderChar`** (string): Character to use for placeholder (defaults to '_')
- **`displayChar`** (string): Character to display for entered values (for secure input)
- **`overwrite`** (string|boolean): Controls overwrite behavior ('shift', true, false)

For more pattern masking options, see: https://imask.js.org/guide.html#masked-pattern

#### Date Masks

Date masks provide structured date input with validation and formatting.

**Example:**
```js
const dateMask = {
  mask: Date,
  pattern: 'MM/DD/YYYY',
  min: new Date(1900, 0, 1),
  max: new Date(2100, 0, 1)
};
```

### `useMaskedValue` (optional)

**Type:** `boolean`  
**Default:** `false`

Controls whether the `onChange` callback receives the masked (formatted) value or the unmasked (raw) value.

- **`false` (default)**: Returns the unmasked value (e.g., "1234567890" for a phone number)
- **`true`**: Returns the masked value (e.g., "(123) 456-7890" for a phone number)

#### Example:

```js
// With useMaskedValue=false (default)
<MaskedField
  mask={{ mask: "(000) 000-0000" }}
  onChange={(e) => console.log(e.target.value)} // Logs: "1234567890"
/>

// With useMaskedValue=true
<MaskedField
  mask={{ mask: "(000) 000-0000" }}
  useMaskedValue={true}
  onChange={(e) => console.log(e.target.value)} // Logs: "(123) 456-7890"
/>
```

<ArgTypes of={MaskedField} />

## Component HTML Structure and Class names

The following HTML is rendered for a MaskedField:

```html
<div class="mobius mobius-text-field">
  <label class="mobius-text-field__label">
    <!-- Label text -->
  </label>
  <input class="mobius-text-field__input" type="text" />
</div>
```

The MaskedField component extends the TextField component and inherits its CSS classes and structure.
