use-mask-input

repository·main·Indexed 20 days ago

https://github.com/eduardoborges/use-mask-input

A lightweight library providing input masking capabilities for React and Vue 3. It supports plain inputs as well as major UI component libraries like Ant Design, and integrates with form libraries including React Hook Form, TanStack Form, and vee-validate.

Tokens
36.6K
Snippets
108
Records
166
Agent score
69%

What's inside use-mask-input

  1. React API Overview for use-mask-input

    main

    The use-mask-input package provides two main entry points. The use-mask-input entry point contains the React API, which includes hooks for standard usage and specialized hooks for integration with React Hook Form and TanStack Form. It also includes Ant Design specific hooks.

    APITypeReact Hook FormAnt DesignNeeds memo?
    useMaskInputHook--No
    useHookFormMaskHookYes-No
    useTanStackFormMaskHook--No
    withMaskFunction--Yes
    withHookFormMaskFunctionYes-Yes
    withTanStackFormMaskFunction--Yes
    useMaskInputAntdHook-YesNo
    useHookFormMaskAntdHookYesYesNo
  2. Vue 3 API Overview for use-mask-input/vue

    main

    The use-mask-input/vue entry point provides the Vue 3 API, consisting of a directive and a composable. Both are compatible with vee-validate and support wrapper components.

    APITypevee-validateWrapper components
    vMaskInputDirectiveYes, no adapterYes
    useMaskInput (Vue)ComposableYes, no adapterYes
  3. Use dynamic mask syntax for variable patterns

    main

    Dynamic masks allow you to define patterns that change or repeat during input using curly braces { }. This is essential for inputs like email addresses, URLs, or IDs where the length or structure is not fixed.

    Syntax Reference

    SyntaxDescription
    {n}Exactly n repetitions
    {n|j}n repetitions with JIT (Just-In-Time) masking
    {n,m}Between n and m repetitions
    {n,m|j}Between n and m repetitions with JIT masking
    {+}One or more repetitions (starts from 1)
    {}Zero or more repetitions (starts from 0)
    /* Syntax Summary */
    {n}      // Exactly n
    {n,m}    // n to m
    {+}
    { }
    {n|j}
    {n,m|j}
  4. How element resolution works with v-mask-input

    main

    The v-mask-input directive and useMaskInput composable are designed to work even when applied to wrappers or third-party Vue components. The library automatically attempts to resolve the underlying <input> or <textarea> element.

    Resolution Logic

    • Wrapper Components: If applied to a component whose root is a <div> containing an <input>, the mask is applied to the inner <input>.
    • Component Instances: If the ref receives a Vue component instance, the library looks at $el. If $el is a wrapper containing an input, it targets that input. If $el is the input itself, it targets it directly.
    • Textareas: If a <textarea> is found within the resolved wrapper, the mask is applied to the textarea.
    • Graceful Failure: If no maskable element (<input> or <textarea>) is found, or if the component uses a fragment root (non-element node), the library resolves without applying a mask and without throwing errors.
  5. Supported Mask Types

    main

    The library supports several types of masking patterns:

    • Static Mask: Fixed patterns like 999-999.
    • Dynamic Mask: Variable-length patterns.
    • Optional Mask: Masks with optional parts.
    • Alias Mask: Built-in presets (e.g., email, currency, datetime).
    • Alternator Mask: Multiple patterns.
    • Preprocessing Mask: Dynamic masks using functions.
  6. Use Preprocessing Masks for dynamic patterns

    main

    Preprocessing masks allow you to define the mask as a function instead of a static string or array. This function is called whenever the mask needs to be evaluated, enabling you to dynamically determine the mask pattern based on external state, API responses, or input conditions.

    React Usage

    Pass a function to the mask property within the useMaskInput configuration object.

    Vue Usage

    In Vue, pass the function through an object binding to the v-mask-input directive. Important: Compute the binding in setup to ensure the function reference remains stable across renders. If a new function is created on every render, the directive will re-apply the mask unnecessarily due to structural comparison.

    // React Example
    import { useMaskInput } from 'use-mask-input';
    
    function DynamicInput() {
      const mask = useMaskInput({
        mask: function() {
          return ['[1-]AAA-999', '[1-]999-AAA'];
        },
      });
    
      return <input type="text" ref={mask} />;
    }
    
    // Vue Example
    <script setup>
    import { vMaskInput } from 'use-mask-input/vue';
    
    const binding = {
      mask: () => ['[1-]AAA-999', '[1-]999-AAA'],
    };
    </script>
    
    <template>
      <input v-mask-input="binding" />
    </template>
  7. How to use unmasked values in Vue templates

    main

    When using use-mask-input in Vue, you cannot use {{ unmaskedValue() }} directly in your template to display the unmasked value. Because reading the DOM does not register a reactive dependency in Vue, the template will render once and never update when the input changes.

    Recommended Pattern: To display the unmasked value reactively in a template, use v-model in conjunction with the autoUnmask option. This ensures the underlying model is updated with the unmasked string, which Vue can then track reactively.

  8. How mask updates and unmounting are handled

    main

    The Vue implementation ensures efficient updates and proper memory management:

    • Smart Re-application: The mask is only re-applied when the bound mask or options change. If the component re-renders with the same mask, the existing input buffer and caret position are preserved.
    • Dynamic Updates: If the bound mask changes (e.g., from 'cpf' to 'cnpj') on an already-mounted element, the new mask is applied immediately.
    • Automatic Cleanup: When an element is unmounted, the Inputmask instance is removed to prevent memory leaks and lingering event listeners.
  9. Use the Vercel Brand Gradient System

    main

    The brand uses a three-pair gradient stack to represent different stages of the workflow. These should be treated as unified objects: do not crop, reorder, or miniaturize them. They are intended for hero-scale atmospheric backdrops.

    - Develop: `{colors.gradient-develop-start}` (`#007cf0`) → `{colors.gradient-develop-end}` (`#00dfd8`)
    - Preview: `{colors.gradient-preview-start}` (`#7928ca`) → `{colors.gradient-preview-end}` (`#ff0080`)
    - Ship: `{colors.gradient-ship-start}` (`#ff4d4d`) → `{colors.gradient-ship-end}` (`#f9cb28`)
  10. Apply Vercel Typography Principles

    main

    To correctly implement the Vercel brand voice via typography, follow these rules:

    1. Negative Tracking: Display sizes MUST use aggressive negative letter-spacing (e.g., -2.4px for 48px). Reverting to default tracking breaks the brand.
    2. Sentence-case & Punctuation: Use sentence-case for headlines and terminate them with a period (e.g., "Build and deploy on the AI Cloud.").
    3. Technical Layering: Use the monospace face ({typography.caption-mono} or {typography.code}) ONLY for technical signals like section eyebrows, code blocks, and terminal mockups. Never use mono for body paragraphs.
    4. Weight Ceiling: The geometric sans should never exceed weight 600.
  11. Vue 3 usage constraints and limitations

    main

    When using the Vue 3 implementation of use-mask-input, be aware of the following technical constraints:

    Reactive Options Limitation

    • No Deep-Watching on Options: The directive re-applies the mask by comparing a cache key. If you provide a reactive options object and mutate a property in-place (without changing the object reference), the directive will not detect the change and will not re-trigger the mask update. To trigger an update, you must provide a new object reference.

    Supported Versions

    • Vue 3 Only: This implementation does not support Vue 2 or the @vue/composition-api package.
  12. How maxlength interacts with masks

    main

    When using a mask that includes literal characters or placeholders, the library manages the native maxlength attribute to prevent conflicts:

    • Literal-bearing masks: If a mask adds characters (like dots or dashes in a 'cpf'), any existing native maxlength attribute is removed. This allows the user to type the full length of the masked string.
    • Open-ended masks: If the mask is purely numeric or does not rely on fixed literals that conflict with length (e.g., a 'numeric' alias), the native maxlength attribute is retained.