段階スキャン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.

プレビュー

  1. 1カートン
  2. 2商品

カートン未選択
  • デスクライト LED梱包 0 / 3
  • USB-C ケーブル 1m梱包 0 / 5

Props

表は横にスクロールできます
プロパティ初期値説明
stagesScanGateStage[]-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.valueunknown-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.
assertiveboolean-Announce results assertively (role="alert" + aria-live="assertive") for safety-critical verify gates. Forwarded to ScanInput. Default false.
showStepsboolean-Show the numbered step indicator. Default true.
autoFocusboolean-Focus the active field on mount and on each advance (scan-gun loop). Default true.
showFeed / feedLimit / lockMsboolean / number / number-Forwarded to the active ScanInput (recent-scan feed, feed cap, double-fire debounce).
refScanGateHandle-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
      },
    },
  ]}
/>