基本情報ブロック
BasicInformation は MUI ベースの、住所と連絡先情報を扱う制御型フォームブロックです。
インストール
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-basic-information-block
yarn add @nodeblocks/frontend-basic-information-block
pnpm add @nodeblocks/frontend-basic-information-block
bun add @nodeblocks/frontend-basic-information-block
必要なもの
| 項目 | 理由 |
|---|---|
data | フォーム状態の単一の信頼源(NameInput, FuriganaInput, PostalCodeInput, PrefectureSelect など) |
onDataChange | 検証、分析、または副作用のための更新済み状態とメタデータを受け取ります |
errors (optional) | フィールドパスをキーにしたフィールドエラー |
labels (optional) | タイトル、サブタイトル、フィールドラベル、検索ボタン文言、送信ボタン文言のルート文言 |
placeholders (optional) | テキストフィールドとセレクトのルートプレースホルダー文言 |
selectOptions (optional) | 都道府県セレクトの選択肢を上書きします |
onSearchAddressClick (optional) | 郵便番号検索ボタンを処理します |
blockSpacingBefore (optional) | デフォルトまたはオーバーライドレイアウト内の指定ブロックの前にカスタム余白を追加します |
BasicInformation はフォーム状態を保持しません。状態はアプリ側で管理し、data に渡してください。デフォルトの形には NameInput, FuriganaInput, PostalCodeInput, PrefectureSelect, CityInput, AddressInput, PhoneInput が含まれます。
コード例
- クイックスタート
- ラベルとコピー
- フォームエラー
- コンパウンドコンポーネント
- ブロックオーバーライド
function Example() { const defaultData = { NameInput: '', FuriganaInput: '', PostalCodeInput: '', PrefectureSelect: '', CityInput: '', AddressInput: '', PhoneInput: '', }; const [data, setData] = React.useState(defaultData); return ( <BasicInformation data={data} onDataChange={setData} onSearchAddressClick={() => { setData((current) => ({ ...current })); }} onSubmit={(event) => { event.preventDefault(); setData((current) => ({ ...current })); }} /> ); }
function Example() { const defaultData = { NameInput: '', FuriganaInput: '', PostalCodeInput: '', PrefectureSelect: '', CityInput: '', AddressInput: '', PhoneInput: '', }; const [data, setData] = React.useState(defaultData); const labels = { title: 'Basic information', subtitle: 'Fields marked * are required.', nameInput: 'Full name', furiganaInput: 'Furigana', postalCodeInput: 'Postal code', searchAddressButton: 'Find address', prefectureSelect: 'Prefecture', cityInput: 'City', addressInput: 'Address', phoneInput: 'Phone number', submitButton: 'Continue', }; const placeholders = { nameInput: 'Enter your full name', furiganaInput: 'Enter furigana', postalCodeInput: 'Enter postal code', prefectureSelect: 'Select a prefecture', cityInput: 'Enter city', addressInput: 'Enter street address', phoneInput: 'Enter phone number', }; return ( <BasicInformation data={data} onDataChange={setData} labels={labels} placeholders={placeholders} onSearchAddressClick={() => { setData((current) => ({ ...current })); }} onSubmit={(event) => { event.preventDefault(); setData((current) => ({ ...current })); }} /> ); }
同じ文言をフォーム全体に適用したい場合は、ルートに文言を渡してください。個別サブコンポーネントを上書きするのは、1つのフィールドだけ別の文言が必要な場合に限ります。このブロックには URL プロパティはなく、利用できるアクションコールバックは郵便番号行の onSearchAddressClick のみです。
function Example() { const defaultData = { NameInput: '', FuriganaInput: '', PostalCodeInput: '', PrefectureSelect: '', CityInput: '', AddressInput: '', PhoneInput: '', }; const defaultErrors = {}; const [data, setData] = React.useState(defaultData); const [errors, setErrors] = React.useState(defaultErrors); const handleDataChange = (nextData, meta) => { const { [meta.name]: _removed, ...restErrors } = errors; const nextErrors = { ...restErrors }; // Validate required fields on blur (same pattern as storybook) if (meta.cause === 'blur') { const value = nextData[meta.name]; if (value === '' || (typeof value === 'string' && !value.trim())) { nextErrors[meta.name] = 'This field is required.'; } } setErrors(nextErrors); setData(nextData); }; return ( <BasicInformation data={data} errors={Object.keys(errors).length ? errors : undefined} onDataChange={handleDataChange} onSearchAddressClick={() => { setData((current) => ({ ...current })); }} onSubmit={(event) => { event.preventDefault(); setData((current) => ({ ...current })); }} /> ); }
function Example() { const defaultData = { NameInput: '', FuriganaInput: '', PostalCodeInput: '', PrefectureSelect: '', CityInput: '', AddressInput: '', PhoneInput: '', }; const [data, setData] = React.useState(defaultData); return ( <BasicInformation data={data} onDataChange={setData} labels={{ searchAddressButton: 'My Search Address' }} onSearchAddressClick={() => { setData((current) => ({ ...current })); }} onSubmit={(event) => { event.preventDefault(); setData((current) => ({ ...current })); }} > <BasicInformation.Title>Basic Information</BasicInformation.Title> <div style={{ display: 'grid', gap: 24 }}> <BasicInformation.Subtitle>Please fill in your basic information</BasicInformation.Subtitle> <BasicInformation.NameInput required={false} /> <BasicInformation.FuriganaInput required={false} /> <BasicInformation.PostalCodeInput required={false} labels={{ postalCodeInput: 'My Postal Code' }} /> <BasicInformation.PrefectureSelect required={false} /> <BasicInformation.CityInput required={false} /> <BasicInformation.AddressInput required={false} /> <BasicInformation.PhoneInput required={false} /> </div> <BasicInformation.SubmitButton>Submit</BasicInformation.SubmitButton> </BasicInformation> ); }
function Example() { const defaultData = { NameInput: '', FuriganaInput: '', PostalCodeInput: '', PrefectureSelect: '', CityInput: '', AddressInput: '', PhoneInput: '', }; const [data, setData] = React.useState(defaultData); const [errors, setErrors] = React.useState({}); const handleDataChange = (nextData, meta) => { const { [meta.name]: _removed, ...restErrors } = errors; const nextErrors = { ...restErrors }; // Validate required fields on blur (same pattern as storybook) if (meta.cause === 'blur') { const value = nextData[meta.name]; if (value === '' || (typeof value === 'string' && !value.trim())) { nextErrors[meta.name] = 'This field is required.'; } } setErrors(nextErrors); setData(nextData); }; return ( <BasicInformation data={data} errors={Object.keys(errors).length ? errors : undefined} onDataChange={handleDataChange} onSearchAddressClick={() => { setData((current) => ({ ...current })); }} blockSpacingBefore={{ customBlock: 2, nameInput: { xs: 4, sm: 3 }, submitButton: 4 }} onSubmit={(event) => { event.preventDefault(); setData((current) => ({ ...current })); }} > {({ defaultBlocks, defaultBlockOrder }) => ({ blocks: { ...defaultBlocks, nameInput: <BasicInformation.NameInput label="Full name" placeholder="Enter your full name" />, customBlock: ( <div style={{ width: '100%', border: '1px solid #cddcff', borderRadius: 8, padding: 12, background: '#eef4ff', fontSize: 14, }} > Custom notification or help text </div> ), }, blockOrder: ['customBlock', ...defaultBlockOrder], })} </BasicInformation> ); }
ブロックオーバーライドを使うタイミング
順序を変更したい場合、デフォルト UI ブロックを置き換えたい場合、または共有状態の処理を維持したままカスタムコンテンツを挿入したい場合にオーバーライドを使います。デフォルトのブロック順は title, subtitle, nameInput, furiganaInput, postalCodeInput, prefectureSelect, cityInput, addressInput, phoneInput, submitButton, input です。blockSpacingBefore はデフォルトまたはオーバーライドレイアウト内の指定ブロックの前に余白を追加します。
重要なプロパティ
コアプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
data | BasicInformationFormData ({ NameInput, FuriganaInput, PostalCodeInput, PrefectureSelect, CityInput, AddressInput, PhoneInput } or extended Record<string, unknown>) | Yes | - | 制御されたフォームデータオブジェクト |
onDataChange | (data, meta) => void | Yes | - | 更新時に呼び出されます。meta には name, value, cause(input, change, blur, clear, reset, programmatic)、および任意の event が含まれます |
errors | { [fieldName: string]: string | string[] } | No | undefined | Field errors keyed by field path; common keys are NameInput, FuriganaInput, PostalCodeInput, PrefectureSelect, CityInput, AddressInput, and PhoneInput |
コンテンツプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
labels | { title?, subtitle?, nameInput?, furiganaInput?, postalCodeInput?, searchAddressButton?, prefectureSelect?, cityInput?, addressInput?, phoneInput?, submitButton? } | No | title: '基本情報', subtitle: '* は必須事項です', nameInput: '氏名', furiganaInput: 'フリガナ', postalCodeInput: '郵便番号', searchAddressButton: '住所を検索', prefectureSelect: '都道府県', cityInput: '市区町村', addressInput: '町名・番地・建物', phoneInput: '連絡先電話番号', submitButton: '次へ' | タイトル、ヘルパーテキスト、フィールドラベル、検索ボタン、送信ボタンのルート文言 |
placeholders | { nameInput?, furiganaInput?, postalCodeInput?, prefectureSelect?, cityInput?, addressInput?, phoneInput? } | No | nameInput: '氏名を入力', furiganaInput: 'フリガナを入力', postalCodeInput: '郵便番号を入力', prefectureSelect: '都道府県を選択', cityInput: '市区町村を入力', addressInput: '町名・番地・建物を入力', phoneInput: '電話番号を入力(ハイフンなしで入力)' | テキスト入力とセレクトのルートプレースホルダー文言 |
selectOptions | { prefectureSelect?: { value: string; label: string }[] } | No | PREFECTURES | 都道府県セレクトに表示する選択肢を上書きします |
onSearchAddressClick | MouseEventHandler<HTMLButtonElement> | No | undefined | 郵便番号検索ボタンを有効にし、ユーザーがクリックしたときに実行されます |
レイアウトと構成のプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
component | StackProps<'form'>['component'] | No | 'form' | ルートコンテナ要素 |
children | ReactNode or block override function | No | undefined | コンパウンドコンポーネント用の JSX children を渡すか、ブロックをオーバーライドする関数を渡します |
blockSpacingBefore | Partial<Record<string, number | { xs?: number; sm?: number; md?: number; lg?: number; xl?: number }>> | No | { subtitle: 4, nameInput: { xs: 4, sm: 3 }, submitButton: 4 } | Extra spacing before selected blocks |
className | string | No | undefined | ルートコンテナの追加クラス名 |
sx | StackProps<'form'>['sx'] | No | undefined | ルートコンテナの MUI sx スタイリング |
Inherits StackProps<'form'> props except children. When using block overrides, the default block order is title, subtitle, nameInput, furiganaInput, postalCodeInput, prefectureSelect, cityInput, addressInput, phoneInput, submitButton, input.
デフォルト UI ブロック
| ブロック | MUI ベースコンポーネント | 備考 |
|---|---|---|
BasicInformation | Stack | ルートフォームコンテナ。component="form" がデフォルトで、組み込みの余白と縦方向の間隔があります |
Title | Typography | デフォルト文言は 基本情報 です |
Subtitle | Typography | デフォルト文言は * は必須事項です です |
NameInput | TextField | name="NameInput"、デフォルトラベルは 氏名、デフォルトプレースホルダーは 氏名を入力 です |
FuriganaInput | TextField | name="FuriganaInput"、デフォルトラベルは フリガナ、デフォルトプレースホルダーは フリガナを入力 です |
PostalCodeInput | TextField + Button | name="PostalCodeInput"、デフォルトラベルは 郵便番号、デフォルトプレースホルダーは 郵便番号を入力、inputMode="numeric"、onSearchAddressClick がある場合の検索ボタン文言のデフォルトは 住所を検索 です |
PrefectureSelect | FormControl + InputLabel + Select + MenuItem | name="PrefectureSelect"、デフォルトラベルは 都道府県、デフォルトプレースホルダーは 都道府県を選択、選択肢のデフォルトは PREFECTURES です |
CityInput | TextField | name="CityInput"、デフォルトラベルは 市区町村、デフォルトプレースホルダーは 市区町村を入力 です |
AddressInput | TextField | name="AddressInput"、デフォルトラベルは 町名・番地・建物、デフォルトプレースホルダーは 町名・番地・建物を入力 です |
PhoneInput | TextField | name="PhoneInput"、デフォルトラベルは 連絡先電話番号、デフォルトプレースホルダーは 電話番号を入力(ハイフンなしで入力)、inputMode="numeric" です |
SubmitButton | Button | デフォルト文言は 次へ です |
追加フィールドプリミティブ
| プリミティブ | MUI ベースコンポーネント | 備考 |
|---|---|---|
Input | TextField | カスタムフローやオーバーライド用に BasicInformation.Input として公開されている内部フィールドプリミティブです |
TypeScript
export type BasicInformationFormData =
| {
NameInput: string;
FuriganaInput: string;
PostalCodeInput: string;
PrefectureSelect: string;
CityInput: string;
AddressInput: string;
PhoneInput: string;
}
| Record<string, unknown>;