import { useState } from "react"; import { ja } from "date-fns/locale"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display"; import { DatePicker, FormField } from "@godxjp/ui/data-entry"; import { Flex, PageContainer } from "@godxjp/ui/layout"; import type { DateRange } from "react-day-picker"; /** * DatePicker — ONE date control. `picker` sets the granularity (day · week · month · quarter · * year), `range` turns it into a two-endpoint field, `multiple` into a set. Always give it a * `name` for form submission; it emits ISO-8601 at the picker's own precision. Use * `minDate`/`maxDate` to constrain what is selectable. Never hand-roll a date input + calendar, * and never compose two DatePickers side-by-side to fake a range — that is `range`. * Composed only from real @godxjp/ui components. */ export default function Demo() { const [issueDate, setIssueDate] = useState(new Date(2026, 0, 15)); const [dueDate, setDueDate] = useState(undefined); const [closingDate, setClosingDate] = useState(undefined); const [meetingDate, setMeetingDate] = useState(new Date(2026, 5, 25)); const [settlementDate, setSettlementDate] = useState(undefined); const [period, setPeriod] = useState({ from: new Date(2026, 3, 1), to: new Date(2027, 2, 31), }); const [term, setTerm] = useState(undefined); return ( 基本 (controlled) value + onValueChange で制御。name= を指定すると ISO yyyy-MM-dd でフォーム送信される。 入力欄に直接タイプでき、カレンダーと同期。フォーカスを外すと正規の ISO 形式に整形され、 解釈できない入力は元の値へ復帰する。 {/* data-axe-open on the region: DatePicker owns its trigger DOM. The gate presses the `[role="combobox"]` input inside, which is what opens the calendar. */} カレンダーの罫線 (bordered) ポップアップのカレンダーは既定で日ごとに罫線を引く (Calendar bordered を転送)。 bordered={"{false}"} で罫線なしに戻せる。range / multiple / week でも同じ。月・四半期・年の グリッドには日のセルがないため対象外。 fromDate で過去日を無効化 支払期限など、今日以降しか選べない場合に fromDate={new Date(2026, 0, 1)} で制限。 fromDate + toDate で範囲を制限 決算締め日など、選択可能期間を会計年度内に絞る場合。 disabled 状態 確定済み伝票など編集不可フィールドに使用。 defaultValue (uncontrolled) value/onValueChange を渡さず defaultValue で初期値だけ与える非制御モード。状態は コンポーネント内部で保持され、name= でそのままフォーム送信できる。 locale で暦の言語を切替 locale={"{ja}"} を渡すとカレンダーの曜日・月名が日本語表示になる。値は ISO-8601 のまま不変で、表示のみ各 locale に追従する。 error 状態 (aria-invalid) FormField の error= を指定すると aria-invalid と role="alert" のエラーメッセージが付与される。必須日付の未入力や範囲外選択の検証結果を提示する。 フッター操作 (showToday / showClose) showToday は今日を選択して閉じる。showClose は選択せずに閉じる。 表示形式と元号 日時の予約 new Date(2026, 8, 10, 9, 0) }]} /> 集計単位 {(["week", "month", "quarter", "year"] as const).map((picker) => ( ))} 複数日を確定 期間 (range) range を付けると値は DateRange になり、開始/終了の 2 入力を 1 つのコントロールにまとめる。 name="period" は period_from / period_to として ISO 送信される。 開始 > 終了で入力しても order (既定 true) が昇順に正規化する。 月次の期間 (range × picker) range と picker は直交する。picker="month" の期間は月グリッドで選び、 term_from / term_to を ISO yyyy-MM で送信する。 期間プリセットと確定 presets · needConfirm · allowEmpty は range でも同じ綴りで効く。 ({ from: new Date(2026, 8, 1), to: new Date(2026, 8, 30) }), }, ]} /> パネルの初期表示 (defaultPickerValue) 値とは独立に「パネルがどの期間を開くか」を指定する。会計年度の開始月で開く、 編集中の行の月で開く、といった要求はこれでしか表現できない。antd と同じく 開くたびに再適用される。 片側だけ固定した期間 range のとき disabled は [from, to] のタプルを取り、片方だけロックできる。 「開始日は契約で確定、終了日だけ交渉中」がこれで表現できる。 disabled な期間 確定済み期間や読み取り専用フィールドに使用。 ); }