Skip to content

Freight Quote

Signals Adapter

Freight Quote

reactiveUmp()
5 rule types

Quote logic mixes predicate requirements, direct field dependencies, mutually exclusive handling branches, admin gating, and promo locks without hand-written orchestration code.

Conditions{ isAdmin: false, promoActive: false }
Conditions
Admin Mode
inactive
FREIGHT50 Promo
inactive
Shipment
required
enabled
disabled
Only business accounts need a company name
required
enabled
required
enabled
Hazmat
enabled
disabled
Enable hazardous materials first
Handling
enabled
enabled
enabled
enabled
enabled
signal state@preact/signals
{
  "conditions": {
    "isAdmin": false,
    "promoActive": false
  },
  "values": {
    "accountType": "personal",
    "serviceLevel": "standard",
    "vehicleType": "van",
    "handlingMode": "none"
  },
  "fouls": []
}

A freight quoting form with 13 fields and 7 rules spanning 5 of Umpire’s 6 rule types. The form adapts to user input, external conditions, and mutually exclusive handling modes — all without hand-written orchestration code.

RuleWhat it does here
requiresCompany name only matters for business accounts. Hazmat class requires the hazardous toggle.
enabledWhenAdmin-only fields (discount override, price hold) gate on the isAdmin condition. Promo locks service level and vehicle type.
oneOfFragile and climate-controlled handling are mutually exclusive branches — picking one hides the other’s fields.
disables(not used here — see the Printer Menu for disables in action)
conditionsisAdmin and promoActive are external facts, not field values. Toggle them with the switches at the top.
  1. Switch account type from Personal to Business — Company Name enables. Switch back and Umpire calls a foul on the stale value with an inline reset button.
  2. Check “Hazardous materials” — Hazmat Class enables. Uncheck it and the class value produces a foul.
  3. Change handling mode from Standard to Fragile — blankets and crate type appear. Switch to Climate-controlled — the fragile fields foul, temp/humidity appear. This is oneOf in action.
  4. Toggle the FREIGHT50 promo — Service Level and Vehicle Type disappear (condition-driven hiding).
  5. Toggle Admin Mode — Discount Override and Price Hold appear.

This demo uses @umpire/signals with Preact and @preact/signals. Each field component reads signal-backed values during render — Preact auto-subscribes and re-renders only the fields that changed.

The entire Umpire integration is the rule definitions and a ~10-line signal adapter. No useEffect, no state synchronization, no manual subscriptions.

const freightUmp = umpire({
fields,
rules: [
requires('companyName', v => v.accountType === 'business'),
requires('hazClass', 'hazardous'),
oneOf('handlingMode', {
fragile: ['blankets', 'crateType'],
climate: ['tempRange', 'humidity'],
}, { activeBranch: v => v.handlingMode === 'none' ? null : v.handlingMode }),
enabledWhen('discountOverride', (_, c) => c.isAdmin),
enabledWhen('priceHold', (_, c) => c.isAdmin),
enabledWhen('serviceLevel', (_, c) => !c.promoActive),
enabledWhen('vehicleType', (_, c) => !c.promoActive),
],
})

Seven rules. That’s the entire form logic. Umpire handles the cascading availability, the fouls when stale values need cleanup, and the per-field reason messages.