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

Quantity Laravel Package

lara-zeus/quantity

Lara Zeus Quantity is a Laravel package for working with quantities and units of measure. Define units, convert values between them, and format quantities cleanly, making it easy to handle product weights, lengths, and other measurements in your applications.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a single-purpose Filament form field: one Field subclass plus one Blade view, no service provider registration and no config publish in the common case. It captures how a quantity is entered — a bounded number with step, precision, and increment/decrement affordances — and nothing about what the quantity means. Reservations, per-warehouse availability, tiered pricing, and unit-of-measure conversion remain in the domain layer regardless of what renders the input. For a TPM, that is the right shape: the dependency is a leaf node in the admin UI, not a load-bearing architectural commitment. The package's own documentation extends this to a combined value + unit field, which is a meaningful scope decision — storing units is a schema choice made on day one and is materially costlier to reverse than the dependency itself.

Integration feasibility. Integration is a one-line install plus a fluent field definition:

composer require lara-zeus/quantity
Quantity::make('quantity')
    ->label('Stock adjustment')
    ->minValue(1)
    ->maxValue(500)
    ->default(1)
    ->required(),

There is no migration, no configuration, and no wiring. Realistic ramp-up to a first working drop-in is under an hour, provided the version matrix resolves. The documented use cases — stock levels, measurements, order quantities, seat/provisioning counts, recipe quantities — map to a recognizable cluster of internal screens that most Filament panels eventually need, so one decision covers several roadmap items with identical interaction.

Technical risk. The risks are concentrated and identifiable, which makes them manageable:

  • Version matrix is the primary blocker, not a footnote. This is a 3.x line built for Filament 3 and Livewire 3. On a Filament 4 panel this is a hard stop. Diff the package's composer.json constraints against the target panel before a ticket is written; discovering incompatibility mid-sprint is the expensive version of this mistake.
  • Bus factor. Single maintainer, 19 stars, zero dependents, 3.0.2 release notes consisting of docs restructuring, two Dependabot CI-action bumps, and one behavioral fix. Read that as stable and cared for, not actively expanding. No SLA exists and none should be assumed.
  • Behavioural change in 3.0.2. Increment/decrement now delays live updates so rapid clicking doesn't fire a request per tap. Any dependent UI (line subtotal, cart badge, running total) may now observe batched rather than per-click updates.
  • Bounds are UX, never enforcement. minValue/maxValue are client-side affordances and Filament validation rules at best. A screen that accepts a quantity the warehouse cannot fulfil because "the field had a max" is a live failure mode.
  • Precision and casts are a silent data-loss vector. A decimal(10,3) column with a field emitting two decimals truncates measurements silently until a report is wrong.
  • Asset staleness. Stale published CSS after an upgrade, or Tailwind content paths missing the vendor directory, produce the classic silent breakage: the field renders unstyled but functional.

Key questions to resolve before commitment.

  1. What does composer.json pin for filament/filament, livewire/livewire, laravel/framework, and php — and does it resolve cleanly against our panels today?
  2. How is the value serialized: one scalar, or number + unit as an array/string? This single answer determines the migration shape and everything downstream.
  3. What are the defaults for getStep() and getPrecision(), and do they agree with our column types and Eloquent casts?
  4. Is the increment/decrement delay interval configurable, and what is the default? It directly sets how laggy a dependent total feels.
  5. Is CSS precompiled or published in our setup, and are vendor paths included in Tailwind content?
  6. What is our documented fallback timeline? A thin Alpine stepper with wire:model.live.debounce is roughly one to two days — that is the ceiling on this dependency's downside.

Integration Approach

Stack fit. The package targets Laravel + Filament 3 + Livewire 3 panels. If the panel is on that stack, fit is essentially perfect (a native Field subclass participating in normal schema, validation, and state handling). If the panel is on Filament 4, stop — this is not a compatibility warning but a re-scope. Confirm the exact namespace (LaraZeus\Quantity\...) and the fluent surface from the README rather than guessing from memory.

Wrap it, always. The highest-leverage day-one decision is a thin internal field component extending the upstream class, so product teams consume a stable internal API and a fork-shaped escape hatch exists from the start:

namespace App\Filament\Forms\Components;

use LaraZeus\Quantity\Quantity;

class StockQuantity extends Quantity
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->label('Quantity')
            ->minValue(1)
            ->maxValue(9999)
            ->step(1)
            ->default(1)
            ->required();
    }
}

Now "our quantity field" is one file, and swapping to a hand-rolled Alpine stepper is hours confined to that file rather than a grep across every resource. Keep the number of named variants small — two or three (StockQuantity, UnitCount, Measurement) is the sweet spot; fifteen signals that options should be passed instead of subclassed. Where the package's unit selector is used, store the unit in a separate, queryable column, not packed into a string, and decide immediately whether unit participates in any pricing or stock lookup key.

Migration path. There is no data migration inherent to adopting the field. The migration-shaped decisions are ours: column types and precision for quantity values, and whether a unit column exists. Set precision explicitly rather than relying on the component default, and align the field, the column type, and the Eloquent cast in one review. Treat any existing hand-rolled steppers or plain number inputs as candidates for consolidation, but convert them per-resource under the shared wrapper rather than in one sweep.

Compatibility and sequencing. Recommended order:

  1. Verify the version matrix against our panels (hours, blocking).
  2. Build the internal wrapper with bounds, step, precision, and default locked in.
  3. Prove it on a single low-blast-radius screen — an inventory adjustment or receiving form on an ops resource — behind a feature flag. Prove three things in one sitting: it renders in our panel theme, it round-trips a value to the database unchanged, and the increment/decrement controls behave under rapid clicking.
  4. Escalate to a Repeater order-line or receiving editor only after the flat field is proven. This is where the field earns its keep and where row-scoped reactivity matters:
Repeater::make('lines')
    ->schema([
        Select::make('product_id')->options(Product::pluck('name', 'id'))->live(),
        StockQuantity::make('quantity')
            ->live(onBlur: true)
            ->afterStateUpdated(function ($state, $set, $get) {
                $price = Product::find($get('product_id'))?->price ?? 0;
                $set('subtotal', round($state * $price, 2));
            }),
    ])
    ->columns(3),
  1. Roll out to remaining resources using the wrapper, adding ->live() only where something genuinely depends on the value.

Prefer afterStateUpdated over computed properties for dependent UI, and keep maxValue and ->rules() fed by the same expression so client bounds and server rules cannot drift.

Validation architecture — two layers, deliberately. The field's minValue/maxValue plus Filament's ->rules() passthrough form the input-affordance layer: immediate feedback, typo prevention. The authoritative check lives in the action or domain service that mutates stock, with a database constraint where the invariant is real. Concurrency is explicitly out of scope — if two admins adjust the same stock row, that requires lockForUpdate() in a transaction or an atomic decrement(); no form field substitutes.

Operational Impact

Maintenance. Ongoing cost is low and largely passive. The concrete obligations are: pin the upstream version in composer.json, keep the package on the dependency-review list, watch release notes for behavioural changes (3.0.2's delayed live update is the template), and keep the wrapper as the only integration surface. Prefer subclassing the wrapper for styling and behaviour over publishing and editing vendor views — a published view quietly diverges on the next composer update and nobody notices until a layout breaks. Because the surface area is a single field, "fork and vendor" is genuinely viable if upstream stalls.

Support. No SLA, single maintainer, negligible community. Support is entirely internal, which is acceptable for an admin-side input control and would not be for anything customer-facing or data-mutating. Plan against the feature set visible today: unit conversion, per-warehouse rules, and richer UX are not coming on request, and no roadmap item should assume otherwise. Document the fallback (one to two days of Alpine work) so the decision is reversible without debate.

Scaling. The component itself does not scale-load anything; it is a form control. What scales is the convention: one component with a documented option set means five squads render and validate quantities identically, which is a quality and consistency lever rather than a customer-facing differentiator. The scaling limits worth watching are process limits — every quantity field becoming ->live() turns form editing into a round-trip-per-change problem, and per-click server-side validation or per-click test assertions are now wrong under the batched update model. Add one explicit test that hammers the increment control in quick succession and asserts the final bound value and request count; it is cheap insurance and directly targets the 3.0.2 regression surface.

Failure modes to instrument or guard.

Failure mode Symptom Guard
Filament 4 panel Install or runtime break Version-matrix check before ticketing
Stale/uncompiled CSS Field renders unstyled but functional Include vendor path in Tailwind content; verify after each bump
Over-max quantity accepted server-side Warehouse cannot fulfil an accepted order Authoritative validation in the action/domain layer + DB constraint
Precision truncation Measurements silently lose digits; reports wrong Set precision explicitly; align field, column type, cast
Batched live updates Dependent totals feel laggy or tests assert per-click requests Re-verify dependents; add rapid-click test
Concurrent stock adjustment Lost update on the same row lockForUpdate() or atomic decrement() in the domain layer
Locale decimal separator Field renders fine but rejects 1,5 Verify numeric input behaviour on non-English panels before standardizing fractional quantities
Upstream abandonment No fixes, no Filament 4 support Pinned version, wrapper boundary, documented Alpine fallback

Ramp-up. Under an hour to a first working drop-in for an engineer already fluent in Filament; half a day including the wrapper component and the three-point proof on a real screen. The first hour should be spent reading the package's composer.json, then the src/ directory and Blade view — specifically to confirm the serialization shape and the getStep()/getPrecision() defaults — rather than trusting the README's option list.

Overall posture. A narrow, low-regret buy: days saved rather than months, blast radius confined to a single form control, MIT licensed, and reversible within two days. The decision is not "is this a good package" but "are we on Filament 3, and do we accept single-maintainer risk for an admin input." If the first answer is yes and the second is mitigated by the wrapper and a pinned version, adopt it and move on. This belongs nowhere near a customer-facing roadmap slide; it is a consistency and quality play for back-office and operations tooling.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource