KQ-1677 · PARCEL/SPEC

Parcel Spec

A shipping form beside an isometric box drawn to scale on a floor of squares: length, width and height are springs, so typing a dimension stretches that edge on springs.snap with one crisp overshoot, switching parcels glides the box to the other parcel's shape on springs.glide, and a box that would outgrow the stage zooms the drawing out on glide while the floor's squares grow to say so. The dial's needle swings to the weight on snap against the chosen service's limit, and each service's balance tips on springs.recoil when a parcel is too heavy for it, greying the service with its reason; quotes from onQuote shimmer while they load and roll in on snap. Fields take any unit ("12 in", "1'6\"", "500 g") and settle into the shown one, Up and Down nudge by one (Shift ten, Alt a tenth), parcels are a tablist where Delete removes one, and services are a radiogroup whose arrows skip the ones that can't go.

KQ-1677 · PARCEL/SPEC

Ship to Halden Street

2 parcels · 7.7 kg

Standard…
6.5 kg
Squares 10 cm

Volumetric 4.8 kg · charged on 6.5 kg

Services

parcel 1 · 40 × 30 × 20 cm · 6.5 kg · quoting…

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/parcel-spec

Props

packages / defaultPackages
ParcelSpecPackage[]
default — / defaultParcelSpecPackages
Parcels in cm and kg: { id, contents?, length, width, height, weight }, controlled or initial.
onChange
(packages) => void
default —
Fires from the keystroke, nudge or button that changed a parcel.
onActivePackageChange
(packageId) => void
default —
The parcel being drawn changed (a tab, a new parcel, a removal).
services
ParcelSpecService[]
default defaultParcelSpecServices
{ id, name, eta, maxWeight (kg), maxLength (cm), base, perKg }.
service / defaultService
string
default — / "standard"
The chosen service, controlled or initial.
onServiceChange
(serviceId) => void
default —
Fires from the click or arrow key that picked a service.
onQuote
(packages) => Record | Promise<Record<string, number | null>>
default —
Prices the parcels per service (null where it can't go); a promise shimmers until it settles. Omit it and prices come from each service's rates.
unitSystem
"metric" | "imperial"
default "metric"
The units fields, callouts, limits and floor squares are shown in; typed units always convert.
boxStyle
"kraft" | "wire" | "tint"
default "kraft"
Cardboard faces with a tape strip, edges only with hidden edges dashed, or accent-tinted glass.
accent
string
default "var(--accent-bright)"
The chosen service, the needle, callouts and focus — any CSS colour; buttons take its hue at a fixed lightness so white text reads in both themes.
maxPackages
number
default 4
Most parcels in one shipment.
volumetricDivisor
number
default 5000
Volumetric weight is L × W × H in cm over this, in kg; the charge uses the greater weight.
heading
string
default "Ship to Halden Street"
The panel's heading and accessible name.
currency
string
default "USD"
The quotes' currency.
locale
string
default "en-US"
The quotes' locale.
status
"ready" | "loading" | "error"
default "ready"
Loading shows a skeleton stage and fields; error shows Try again.
onRetry
() => void
default —
Try again was pressed after the shipment failed to load.
height
number
default 540
The panel's height in px.
disabled
boolean
default false
Nothing can be edited.
className
string
default —
Classes for the panel.