import { useState } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display"; import { FormField, NumberInput } from "@godxjp/ui/data-entry"; import { Flex, PageContainer } from "@godxjp/ui/layout"; import { Heading, Text } from "@godxjp/ui/general"; /** * NumberInput — WAI-ARIA spinbutton for localized numeric entry. Composes the real `Input` * primitive (role="spinbutton", inputMode="decimal") with stacked increment/decrement `Button`s. * Type freely, ArrowUp/ArrowDown (Shift = ×10) step, value commits clamped to min/max + rounded to * precision on blur/Enter. Steppers disable at the bounds. Composed only from real @godxjp/ui. */ export default function Demo() { const [quantity, setQuantity] = useState(1); const [rating, setRating] = useState(3); const [price, setPrice] = useState(1980); const [discount, setDiscount] = useState(10); return ( 基本 (controlled) value + onValueChange で number | null を制御。空欄は null。ArrowUp/Down またはステッパーで step ずつ増減。 現在値: {quantity ?? "(空)"} min / max · 範囲クランプ min=1, max=5。境界でステッパーが無効化され、コミット時に範囲内へクランプされる。 step · 刻み幅 step=100 で 100 単位の増減。Shift + Arrow で ×10 (1000 刻み)。 precision · 小数桁 precision=2, step=0.25。コミット時に小数 2 桁へ丸め、Intl.NumberFormat で整形。 prefix / suffix — ¥ と % 通貨記号や単位を装飾的な affix として表示 (aria-hidden)。値は生の数値のまま。 uncontrolled (defaultValue) React 管理不要なネイティブフォーム。送信時に name 経由で値が渡される。 disabled / readOnly disabled は操作不可、readOnly は値を表示・選択できるが編集・ステップ不可。 size · xs / sm / md / lg 制御高さティア (--control-height) に連動。行内の他コントロールと整列。 {/* prefix / suffix — all THREE combinations, because the two-affix case is the only one that used to be exercised and the suffix-only one is where the bug lived. */} prefix · suffix · 単位つきの数値 通貨記号や単位はフィールドの内側に重ねる装飾。読み上げからは外れる (aria-hidden) ので、意味は必ずラベル側に置く。 キーボード操作 ↑ / ↓ で step 増減・Shift + ↑ / ↓ で ×10・Enter で確定 (クランプ + 丸め)・Tab でフォーカス移動。ステッパーは tabIndex=-1 でキーボードのタブ順を汚さない。 ); }