chengkangzai/filament-qrcode-scanner-html5
A Filament form component that adds an HTML5 QR code scanner using the device camera. Scan codes directly in the browser and populate form fields without a native app. Easy to drop into Filament forms for quick, mobile-friendly scanning workflows.
What this package is: a Filament form-component extension that attaches a camera-driven barcode/QR scanner as an affix action on an input field. The action opens a modal, captures frames in the browser, decodes them client-side, and pushes the result into the Livewire form state via $wire.set(). It is a UI-layer plugin: no server-side scanning, no queue, no external service dependency, no persistence of its own.
Architecture fit: Good fit for our stack if we are already on Filament for admin/internal tooling. It behaves as a composable field-level action rather than a page or resource concern, which keeps it out of our domain layer — always a plus for a UI plugin. The main architectural coupling is to Filament's action lifecycle (isVisible() / isHidden()), and this release is precisely a lesson in how tight that coupling is: the package had assumed disabled on a field wrapper would suppress the affix, and it does not. That is a framework-contract assumption, not a bug in our code, and it means our exposure to Filament internal changes is non-trivial.
Integration feasibility: Low effort. Registration is per-field (add the action to the input), so adoption can be incremental and scoped to the handful of fields that actually need scanning (asset tags, SKU entry, bin locations). No migrations, no config publishing required for basic use, no server footprint. The camera path does imply an HTTPS origin and browser permission flow, which is an environment prerequisite rather than an integration task, but it does affect where the feature can be demoed (localhost or TLS only).
Technical risk:
hideWhenFieldDisabled() opt-out, but the team must know it exists. Treat this as a minor-version change in spirit and test accordingly.$wire.set() bypasses the input element. Server-side validation and any reactive()/afterStateUpdated() chains still fire on the Livewire side, but there is no keystroke-level sanitization or masking applied. Fields with input masks or maxLength should be verified explicitly.isHidden() rather than calling ->hidden(), deliberately, so a consumer's own ->hidden() condition is not clobbered. That is the right call for composability, but overriding a lifecycle method is a sharper edge than composing a flag — worth a regression test on our side if we stack our own visibility conditions on the same action.Key questions for the maintainer:
isHidden() override stable across them?Stack fit: Assumes Laravel + Livewire + Filament, PHP 8.x, and a modern evergreen browser on the client. It slots in as a composer require dev-to-prod dependency with no infrastructure change. If we are not on Filament for the target surface, this package is not applicable and the effort should go to a standalone scanner component instead — worth settling before any spike work.
Migration path: There is nothing to migrate. Adoption is additive and per-field; removal is deleting an action from a form schema and dropping the dependency. That reversibility is the strongest argument for piloting it on one screen rather than standardizing it.
Compatibility: Pin ^2.1.3 rather than a floating constraint. Anyone on 2.1.2 or earlier should be upgraded, not because 2.1.3 is optional but because 2.1.2 contains a silent data-loss-adjacent UX defect: on a Filament view page, where ViewRecord::defaultForm() renders the edit form with ->disabled(), the scanner button rendered and rewrote a field the form could never persist. Users read that as an edit that did nothing. If we use view/infolist pages with disabled forms, this upgrade is mandatory, not opportunistic.
Sequencing:
BarcodeScannerAction. Classify each as type-and-scan (new default is correct) or scan-only (must add hideWhenFieldDisabled() plus ->dehydrated()). This classification is the entire migration and it is easy to skip.->hidden() conditions on the same action, assert they still apply — that is the exact case the new override was designed to protect.Maintenance: Small surface area, single dependency, no runtime services. The ongoing cost is tracking Filament majors — the disabled/visible interaction that caused this bug is exactly the class of change that moves between Filament releases, so budget a re-verification pass on every Filament upgrade rather than assuming the plugin keeps up. Vendor and bus-factor risk should be recorded in the dependency register; this looks like a small-maintainer package, so pinning and a fork option matter.
Support: Most inbound tickets will be environmental, not code: camera permission denied, non-HTTPS origin, no camera on a desktop, an unreadable or damaged barcode. The new hidden-when-disabled behavior is a second, subtler ticket source — "the scan button vanished" after upgrade — and will look like a regression to users unless we pre-brief the floor and document hideWhenFieldDisabled() for whoever maintains the form schemas.
Scaling: Effectively free. Decoding is client-side and the write is a single Livewire round trip, so cost per scan is one small request regardless of concurrency; there is no server-side image pipeline to size. The real ceiling is client device performance and browser support, not our infrastructure. Worth noting for capacity planning only in the sense that the feature's availability is bounded by hardware refresh cycles on the floor.
Failure modes:
->hidden() conditions interacting with the new isHidden() override — low probability, cheap to test.Ramp-up: Hours for a Filament-fluent developer to wire up and read the source; the API is one action plus one opt-out method. The harder ramp is operational: floor users need a short script on the permission prompt and on what to do when a barcode won't read, and the team maintaining form schemas needs the disabled-versus-scan-only distinction written down. Net assessment: v2.1.3 is a clear improvement and the release that makes this package safe to adopt on disabled forms — approve, pin ^2.1.3, and pair adoption with the field-classification audit above.
How can I help you explore Laravel packages today?