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

Nova Percent Field Laravel Package

nsavinov/nova-percent-field

A Laravel Nova field for entering and displaying percentage values. Adds a dedicated percent input with formatting and validation, so percentages store and render cleanly in Nova resources without custom field code.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a single-purpose Laravel Nova form field that renders a numeric input with percent semantics — a % affordance and, optionally, a scaling transform between the stored value and the displayed value. It lives entirely inside the Nova admin layer: no domain logic, no validation policy, no API or reporting surface, no service-provider wiring beyond Nova's own asset registration. For a TPM the classification should be stated in the intake note plainly: this is a tactical UI convenience, not a platform component. It should never sit on an architecture diagram in a position that implies strategic dependency, and it should never be load-bearing for a pricing, tax, commission, or payout capability.

Integration feasibility. Superficially trivial — one composer require, then Percent::make('Discount Rate') on a resource. The real feasibility question is version compatibility, and that is where the package's age dominates. The last release is 2018-09-26, placing it in the Nova 1/2 era: Vue 2, Laravel Mix, Nova::script() / prebuilt dist/js/field.js asset registration. Nova is not on Packagist, so the laravel/nova constraint in the package composer.json is effectively a hard pin against an old major. On a modern Nova install the require will likely fail to resolve, or install against a stale constraint. That means the honest feasibility answer is "port, not drop-in" until a compatibility spike proves otherwise.

Technical risk.

  • Lifecycle risk (high, unavoidable). 21 stars, zero dependents, no release in ~7 years. No upstream maintainer to lean on.
  • Runtime risk (high on modern Nova). The 2018 asset pattern may not mount under a Vite-built Nova; the FormField.vue component may never register. Budget a component rewrite.
  • Correctness risk (medium, and it's the kind that produces bad data). null coerced to 0 silently turns "no discount set" into "0% discount"; asymmetric save/display transforms produce "saved 1500%" bugs; the default step of 1 blocks 12.5 in the browser with no server-side error; client-side min/max is a hint, not validation, and is bypassed by API writes, Nova actions, and pasted input.
  • Data-contract risk (medium, but owned upstream of this package). Adopting it forces a storage convention — whole percent (15 = 15%) or fraction (0.15 = 15%) — that must be enforced across seeders, factories, API resources, imports, exports, and reporting.

Key questions to resolve before any commitment.

  1. Which Nova major are we on, and what does the package's laravel/nova constraint actually say?
  2. Does boot() use Nova::script() against a prebuilt dist/js/field.js, and does our Nova still support that pattern?
  3. Which side of the transform does our database column live on — and who signs off on that contract (finance/reporting owner, not just engineering)?
  4. Who is the named owner of the forked code, and what is the replacement trigger?
  5. Is the native Number::make('Rate')->step(0.01)->min(0)->max(100)->suffix('%')->rules(...) genuinely insufficient, or are we carrying a dependency for cosmetics?

Integration Approach

Stack fit. Fits Laravel + Nova admin panels only, and realistically Nova 1/2-era stacks. It is not a fit for a Vite-built modern Nova without a port, and it is not a fit for any surface outside the admin panel — public forms, APIs, or customer-facing UI all sit outside its scope.

Migration path. There is no migration to this package worth planning as a project. The decision is framed correctly as a build-vs-buy call where "build" (or rather, "use what Nova already ships") frequently wins. Native Number with step, min, max, suffix('%'), and rules(...) covers most admin needs with zero third-party surface area. Reach for this package only when maintaining an existing install that already depends on it, or when the fraction-to-percent display convention genuinely earns its keep on a compatible Nova version.

Compatibility approach. Verify, don't assume. The sequence is: read composer.json for the laravel/nova constraint → read src/ to confirm the field extends Laravel\Nova\Fields\Number (and inherit rules/nullable/sortable for free) → read boot() for the asset registration pattern → read resources/js/components/FormField.vue, which is where the actual percent behaviour (scaling, rounding, % suffix, null handling) lives. The PHP class is thin; the component is the product. If the constraint won't resolve, fork it, loosen the constraint, and pull it in via a VCS or path repository.

Sequencing.

  1. Compatibility spike (timeboxed). Confirm Nova major, constraint, asset pattern, and whether the component mounts. If it doesn't, decide fork-vs-replace before writing feature code.
  2. Storage contract decision. Whole percent vs fraction, documented and signed off by whoever owns finance exports and reporting. Enforce it in one place.
  3. Wrapper field. A single App\Nova\Fields\Percent that extends or composes the package field and sets standard rules, step, and formatting. One file to patch when we fork, one file to delete when we replace it with native Number.
  4. Symmetric transforms. If scaling is needed, do it in fillUsing/resolveUsing as exact inverses — and test the round trip. This is the single test worth writing.
  5. Server-side rules. Mirror every client-side min/max/step into ->rules(); the field will not do it for you.
  6. Contained rollout. Pin the dependency, validate in staging, internal users only.

Operational Impact

Maintenance. The PM decision is not "adopt a vendor package" — it is "accept and own a small piece of vendored code." With 21 stars, zero dependents, and a 2018 release, assume upstream is inert. The wrapper-field pattern is what keeps the maintenance tax small: one file to own, one file to patch, one file to delete. Approve only if that ownership is explicitly someone's job.

Support. None. No maintained support, no security updates, no community to escalate to. Any defect is ours to fix, and any future Nova major upgrade likely forces a FormField.vue rewrite. That should be a planned cost, not a surprise.

Scaling. Not a meaningful concern for this package — it's a form field with no throughput, storage, or compute footprint of its own. The scaling question is organizational: how many resources adopt it, and how consistently the storage contract is held across them. Inconsistency here is what creates downstream reporting bugs, not load.

Failure modes to instrument and document.

  • null → 0 coercion silently converting "no discount set" into "0% discount" — add explicit null guards on both sides and check setInitialValue/prepare.
  • Asymmetric save/display transforms producing "saved 1500%" bugs — the pair must be exact inverses; test round-tripping.
  • step default of 1 blocking 12.5 at the browser level with no server-side error to explain it — set step deliberately.
  • Client-side min/max mistaken for validation — API writes, Nova actions, and pasted input bypass it entirely; duplicate in ->rules().
  • Silent non-render — a 404 on dist/js/field.js or a stale nova:publish; also Nova::script() registrations fail silently if two fields reuse the same key, a real hazard if a fork lives alongside the original.
  • Locale separators — comma-decimal users typing 12,5; the 2018-era component almost certainly assumes a dot and may truncate silently. Normalise server-side or document the limitation for internal users.
  • Sortable mismatch — with a display transform, sortable() sorts the raw column while the header shows a scaled value. Usually harmless for monotonic transforms; confirm it before someone files a "wrong ordering" bug.

Ramp-up. Low for a Nova-fluent engineer — the integration surface is one field and a Vue component. The real ramp-up cost is the compatibility spike and the contingency for a FormField.vue rewrite. Budget both up front, and set the replacement trigger now: the next Nova major upgrade is the natural moment to retire this in favor of native Number formatting or a small custom field.

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.
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
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox