Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Input Mask Laravel Package

wemersonrv/input-mask

A Laravel package that adds input masking to forms via Blade components, with ready-to-use masks for CPF/CNPJ, phone, date, currency, and custom patterns.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the source before the README. The package description says "Blade directives and helpers," which reads like a general Laravel form library. The repository is a Laravel Nova custom field: a PHP Field subclass plus a Vue component that renders a masked input inside Nova's resource forms. It does nothing in Blade, Livewire, or Inertia. Plan against src/ and resources/js/, not the marketing copy.

Verify three things before writing integration code:

  1. Your Nova major. Last release is 2019-05-16, which lands in the Nova 1.x/2.x era (Vue 2). Nova 3 changed field internals; Nova 4/5 moved to Vue 3. On Nova 4+ assume the frontend is broken and the install step degrades to "port it."
  2. The license. GPL-3.0 is a genuine outlier in an MIT-almost-everywhere ecosystem. Internal unmodified use is usually defensible; distributed, on-prem, or client-delivered code triggers copyleft. Get sign-off before the spike, not after.
  3. The actual API surface. composer.json for the laravel/nova and PHP constraints, package.json for the bundled JS mask plugin (name, version, license), and the Field class for the exact namespace and fluent setter name — the snippet below is illustrative, not guaranteed.

Minimal steps (on a branch, in a legacy Nova install):

composer require wemersonrv/input-mask
use Wemersonrv\InputMask\InputMask; // verify namespace in src/

public function fields(Request $request)
{
    return [
        InputMask::make('Phone')
            ->mask('(99) 99999-9999'), // verify setter name in the Field class
    ];
}

Then run php artisan nova:publish / npm run dev if the field ships unbuilt assets, load the resource form, and submit it and inspect the database row. This is the step people skip. You are verifying whether the field strips mask characters or persists (11) 99999-8888 verbatim — that answer drives every downstream decision about validation, search, and exports.

First use case: a single internal-admin field where operators type a Brazilian format (CPF, CNPJ, phone, postal code, date, currency). Not customer-facing forms, not anything feeding an export or an integration.

Where to look first: the src/ Field class (the entire PHP API — likely a make() plus one metadata setter), the Vue component in resources/js/ (the entire behavior), and the bundled mask library. The package is small enough that the source is the documentation; read all three before touching a resource.

Implementation Patterns

Wrap it in your own field class. Don't sprinkle Wemersonrv\InputMask\InputMask::make() through twenty resources — the upstream name is your migration liability.

namespace App\Nova\Fields;

class MaskedText extends \Wemersonrv\InputMask\InputMask
{
    public function phone(): static    { return $this->mask('(99) 99999-9999'); }
    public function document(): static { return $this->mask('999.999.999-99'); }
    public function postalCode(): static { return $this->mask('99999-999'); }
}

When you swap the underlying component (or port to Vue 3), every call site stays untouched.

Treat the mask as presentation and put the real logic in the request layer. This is what makes the field swappable:

protected function prepareForValidation(): void
{
    $this->merge([
        'phone'    => preg_replace('/\D+/', '', (string) $this->input('phone')),
        'document' => preg_replace('/\D+/', '', (string) $this->input('document')),
    ]);
}

Normalize before validation so rules speak in canonical digits (->rules('digits:11'), not a regex that has to account for parentheses). Persist the normalized form; re-apply the mask only at render time. For currency, parse to integer minor units; for dates, Carbon::createFromFormat against the expected pattern with a fallback.

Pair every masked field with a display formatter. Stored 11999998888 is unreadable in index and detail views. Add a Nova Text field using ->displayUsing(fn ($v) => format_phone($v)), or a model accessor if the value is used outside Nova. Otherwise the mask's benefit exists only inside the edit form.

Decide one direction and hold it across the codebase. Either (a) store unmasked and format on display — best for search, joins, and exports; or (b) store masked and normalize on read — only if legacy columns already contain punctuation. Mixing shapes across resources is how you get "why doesn't search find this record."

Reference-implementation pattern (the realistic one for modern Nova). Read the two source files, then rebuild: copy the Vue component, replace the bundled mask plugin with a maintained one (IMask or cleave.js), bump to Vue 3, and publish it as a local Nova component in nova-components/. You get version control, an MIT-clean license, and a mask library you chose. This is a one-to-two-day job and usually cheaper than making the 2019 asset pipeline cooperate.

Spike matrix — test the exact tokens you intend to use, not just "does it render":

Action What to confirm
Type a full value Characters land in the right slots
Paste a pre-formatted value Not doubled or truncated
Paste a bare-digit value Mask applies, no mangling
Clear the field Emits empty, not placeholder debris
Submit empty Server rule behaves
Browser autofill Doesn't bypass or break the mask
Server-side submit via curl Confirms the mask is not a validation layer

That last row is the one that matters most: post the form directly, bypassing the UI, and confirm your validation rejects bad input. Mask libraries diverge sharply on paste and autofill.

Gotchas and Tips

  • GPL-3.0 is a release gate, not a footnote. In a commercial or distributed product this needs legal review. If that review is expensive, build the field yourself — the code is ~2 files.
  • Masks format; they never validate. A paste, a crafted request, or curl bypasses the widget entirely. Every masked field needs a server-side rule and a normalization test. If a stakeholder frames this as "solving our data quality problem," correct that in the same meeting.
  • The field almost certainly submits the masked string. Verified by inspecting the DB row. If so, any rule assuming digits silently fails, and any LIKE/join/export against that column is wrong. Normalize at the FormRequest or model boundary rather than migrating the schema mid-project.
  • Nova major-version breakage is scheduled, not hypothetical. A 2019 Vue 2 component on Nova 4 is a rewrite. Confirm your Nova version before committing sprint capacity — that single answer decides adopt vs. build.
  • No maintainer means no security path. The durable risk sits one layer down: the bundled JS mask library, whose version, CVE state, and input handling are unexamined. If you adopt, pin the exact version and fork it into private VCS with a named owner; otherwise it rots silently in the dependency tree.
  • The extension point is the Vue component, not the PHP. All behavior lives in resources/js/; the PHP class only passes metadata. Customizing means editing and rebuilding that component — and owning the rebuild forever. "Just patch it" is rarely the cheap option it looks like.
  • Debugging a field that "stopped formatting": dump $field->meta() inside fields() to confirm mask metadata reaches the frontend, then check the Nova browser console for a failed registration (Nova.booting) error. Nine times out of ten it's a Vue version mismatch or an unbundled asset, not the mask config.
  • Paste and autofill are the common production failure. A user pasting a pre-formatted CPF into a field that assumes bare digits gets mangled input. Test both, and normalize defensively server-side regardless of what the widget claims.
  • Accessibility is unowned. Masked inputs that silently swallow keystrokes confuse screen-reader and keyboard-only users. Add help text stating the expected format if your admin tooling has accessibility commitments.
  • Don't bolt this onto public-facing forms. Its presets are Brazilian and its toolchain is 2019-era. For customer-visible surfaces, evaluate a maintained mask library against your own design system.
  • Dynamic masks (e.g., a document field that switches CPF↔CNPJ based on a type select) require logic in the Vue component — the PHP side only passes a static string. Budget for that as custom frontend work, not configuration.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log