段階スキャンScanGateExperimental
Staged barcode scan flow: ordered ScanInput stages (e.g. location→item, carton→item) where each stage resolves a confirmed context the next stage reads, auto-advancing and re-focusing between steps. For WMS picking, put-away and packing where you scan-to-confirm before scan-to-count.
プレビュー
Props
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| stages | ScanGateStage[] | - | Ordered scan stages. Each has id / label / onScan(code, ctx) => ScanGateResult. The first stage is active initially. |
| ScanGateResult.advance | "next" | "stay" | "reset" | "done" | stageId | - | Returned from onScan to control flow. "next" advances (wraps + clears on the last stage = one cycle, for cyclic flows like packing), "stay" remains, "reset" returns to the first stage and clears context, "done" completes a terminating flow (holds the stage, keeps context, fires onComplete — use on the last stage of a verify-then-act gate), a stage id jumps. Default ok ? "next" : "stay". |
| ScanGateResult.value | unknown | - | Remember a confirmed value for the stage; later stages read it via ctx.values[stageId]. |
| onStageChange | (stageId, ctx) => void | - | Notified when the active stage changes. |
| onComplete | (ctx) => void | - | Fired when a stage returns advance:"done" — the terminating flow is complete; ctx holds the verified values. |
| assertive | boolean | - | Announce results assertively (role="alert" + aria-live="assertive") for safety-critical verify gates. Forwarded to ScanInput. Default false. |
| showSteps | boolean | - | Show the numbered step indicator. Default true. |
| autoFocus | boolean | - | Focus the active field on mount and on each advance (scan-gun loop). Default true. |
| showFeed / feedLimit / lockMs | boolean / number / number | - | Forwarded to the active ScanInput (recent-scan feed, feed cap, double-fire debounce). |
| ref | ScanGateHandle | - | Imperative handle: reset() (back to first stage + clear), goTo(stageId), getValues(). Use for a 'close carton' button. |
Usage
import { ScanGate, type ScanGateResult } from "@gunjo/ui"
// carton → item packing: scan a carton to open it, then scan items into it
<ScanGate
stages={[
{
id: "carton",
label: "① カートンをスキャン",
onScan: (code): ScanGateResult => {
const carton = openCarton(code)
if (!carton) return { ok: false, message: "カートンが見つかりません", advance: "stay" }
return { ok: true, message: `${code} を開きました`, advance: "next", value: carton }
},
},
{
id: "item",
label: "② 商品をスキャン",
onScan: (code, ctx): ScanGateResult => {
const carton = ctx.values.carton // confirmed in the previous stage
const line = pack(code, carton)
if (!line) return { ok: false, message: "受注に無い商品", advance: "stay" }
return { ok: true, message: `${line.name} を梱包`, advance: "stay" } // keep packing
},
},
]}
/>