react-pin-field

repository·master·Indexed 19 days ago

https://github.com/soywod/react-pin-field

A lightweight, accessible React component for entering PIN codes. It supports multi-input PIN entry with RTL support, ARIA labels, and both controlled and uncontrolled modes. The library provides the PinField component for UI rendering and the usePinField hook for custom state management and logic, including automatic focus management and customizable character formatting.

Tokens
2.4K
Snippets
8
Records
12
Agent score
64%

What's inside react-pin-field

  1. How to use the usePinField hook for controlled state

    master

    By default, PinField is an uncontrolled component. To control the PIN code state (e.g., to programmatically set the value or clear it), use the usePinField hook and pass the returned handler to the PinField component via the handler prop.

    const handler = usePinField();
    
    // The handler exposes 'value' and 'setValue' to control the PIN code,
    // as well as 'state' and 'dispatch' for advanced usage.
    
    return <PinField handler={handler} />;
  2. Style the PinField component

    master
    You can style the PinField using the standard React style prop or the className prop. Using className is recommended if you want to leverage CSS pseudo-classes like :nth-of-type, :focus, :hover, :valid, or :invalid on the individual input elements.
  3. Access individual input elements via ref

    master

    The PinField component exposes a special reference that returns an array of HTMLInputElement objects. This allows you to programmatically interact with specific inputs, such as focusing a particular index.

    const ref = useRef<HTMLInputElement[]>();
    
    <PinField ref={ref} />;
    
    // Example: focus the third input
    ref.current?.[2].focus();
  4. Configure PinField props

    master

    The PinField component inherits most props from HTMLInputElement, but overrides several event handlers. You can use the following props to customize its behavior:

    • length: The number of input fields in the PIN sequence. Defaults to 5.
    • format: A function (char: string) => string to format each character entered. Defaults to an identity function.
    • formatAriaLabel: A function (index: number, total: number) => string to generate accessible labels for each input. Defaults to "PIN field ${n} of ${total}".
    • onChange: A callback function (value: string) => void called whenever the PIN value changes.
    • onComplete: A callback function (value: string) => void called when every input has a value and passes standard HTML validation (like required or pattern).
  5. Access underlying input elements via ref

    master

    The PinField component uses forwardRef to expose the underlying DOM elements. The ref provided to PinField will resolve to an array of HTMLInputElement objects, where each index corresponds to the input field for that position in the PIN.

    import { useRef } from 'react';
    import { PinField } from 'react-pin-field';
    
    function MyComponent() {
      const inputRefs = useRef<HTMLInputElement[]>([]);
    
      const focusLastInput = () => {
        const lastInput = inputRefs.current[inputRefs.current.length - 1];
        if (lastInput) lastInput.focus();
      };
    
      return (
        <>
          <PinField ref={inputRefs} length={6} />
          <button onClick={focusLastInput}>Focus Last</button>
        </>
      );
    }
  6. Configure the PinField component props

    master

    The PinField component accepts a combination of standard HTML input attributes and specialized props for managing PIN entry.

    Native Props

    PinField inherits from InputHTMLAttributes<HTMLInputElement>, but the following props are omitted and replaced by the library's internal logic to ensure correct PIN handling:

    • onChange
    • onKeyDown
    • onCompositionStart
    • onCompositionEnd

    By default, the component uses type="text", inputMode="text", autoCapitalize="off", autoCorrect="off", and autoComplete="off" to prevent unexpected browser behavior during PIN entry.

    PinField Specific Props

    These props control the behavior and accessibility of the PIN field:

    • length (number): The required number of characters in the PIN. Defaults to 5.
    • format (function): A function (char: string) => string used to transform each character as it is entered.
    • formatAriaLabel (function): A function (index: number, total: number) => string used to generate accessibility labels for each digit. Defaults to `PIN field ${index} of ${total}`.
    • onChange (function): A callback (value: string) => void triggered whenever the PIN value changes.
    • onComplete (function): A callback (value: string) => void triggered when the PIN reaches the specified length.
    • handler (Handler): An optional custom handler for managing the PIN logic.
  7. Use the PinField component

    master

    The PinField component is the primary UI element for rendering a series of input fields for PIN entry. It renders a collection of individual <input> elements, one for each character in the PIN. It supports custom formatting, length configuration, and provides lifecycle callbacks for changes and completion.

    Key features:

    • Automatic Focus Management: Handles moving focus between inputs as the user types.
    • RTL Support: Automatically reverses the input order if the dir prop is set to rtl.
    • Accessibility: Uses formatAriaLabel to provide meaningful labels for each input field.
    • Ref Forwarding: The component forwards a ref that resolves to an array of HTMLInputElements, allowing direct access to the underlying DOM nodes.
    import { PinField } from 'react-pin-field';
    
    function MyComponent() {
      return (
        <PinField 
          length={4} 
          onChange={(value) => console.log('Current PIN:', value)}
          onComplete={(value) => console.log('PIN completed:', value)}
        />
      );
    }
  8. Use the usePinField hook to manage PIN field logic

    master

    The usePinField hook provides the core logic and state management for a PIN input field. It returns a Handler object containing everything needed to synchronize multiple input elements with a single PIN value.

    To use it, call usePinField() and destructure the returned properties. You will typically use refs to attach to your individual input elements, state to determine the status of each digit (like focus or error), and value to get the current full PIN string.

    Returned Handler Object

    PropertyTypeDescription
    refsRefObject<HTMLInputElement[]>An array of refs to be attached to each individual PIN input element.
    stateStateThe current state of the PIN field (e.g., length, values, cursor position).
    dispatchActionDispatch<[Action]>A function to manually dispatch actions to the PIN field reducer.
    valuestringThe current concatenated PIN value as a single string.
    setValue(value: string) => voidA function to programmatically set the entire PIN value.

    Example Usage

    import { usePinField } from 'react-pin-field';
    
    function MyPinComponent() {
      const { refs, state, value, setValue } = usePinField();
    
      return (
        <div>
          <div style={{ display: 'flex', gap: '8px' }}>
            {/* Create an input for each digit in the state length */}
            {Array.from({ length: state.length }).map((_, index) => (
              <input
                key={index}
                ref={(el) => (refs.current[index] = el!)}
                value={state.values[index] || ''}
                // ... other input props
              />
            ))}
          </div>
          <p>Current PIN: {value}</p>
        </div>
      );
    }
    import { usePinField } from 'react-pin-field';
    
    function MyPinComponent() {
      const { refs, state, value, setValue } = usePinField();
    
      return (
        <div>
          <div style={{ display: 'flex', gap: '8px' }}>
            {Array.from({ length: state.length }).map((_, index) => (
              <input
                key={index}
                ref={(el) => (refs.current[index] = el!)}
                value={state.values[index] || ''}
              />
            ))}
          </div>
          <p>Current PIN: {value}</p>
        </div>
      );
    }
  9. Access PinField actions, hooks, and state

    master

    The react-pin-field package exports several modules to allow for advanced control and customization of the PIN field:

    • Actions: Functions to trigger specific behaviors in the PIN field.
    • Hooks: React hooks (like usePinField) to access the field's internal state and methods.
    • Props: TypeScript types defining the configuration for the PinField component.
    • Reducer/State: Internal logic and state structures for managing the PIN value and field status.
  10. Use the PinField component

    master

    The PinField component is the primary entrypoint for creating a PIN input field. It is exported as the default export from the package. You can import it directly to render a controlled or uncontrolled PIN input field.

    import PinField from 'react-pin-field';
    
    function MyComponent() {
      return <PinField />;
    }