基本情報ブロック
BasicInformationコンポーネントは、React、TypeScript、MUIで構築された、ユーザーの基本情報を収集するための完全にカスタマイズ可能でアクセシブルなフォームです。モダンなデザインパターン、react-hook-formを使用したフォームバリデーション、柔軟なカスタマイズオプションを備えた完全な住所と連絡先情報のインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-basic-information-block@0.2.0
📖 使用法
import {BasicInformation} from '@nodeblocks/frontend-basic-information-block';
- 基本的な使用法
- 高度な使用法
function BasicInformationForm() { return ( <BasicInformation onChange={(setError, getValues) => { console.log('フォーム値:', getValues()); const values = getValues(); if (!values.NameInput) { setError('NameInput', {message: '氏名は必須です', type: 'required'}); } }} onSubmit={formData => { console.log('フォームが送信されました:', formData); }} onInvalid={errors => { console.log('フォームバリデーションエラー:', errors); }}> <BasicInformation.Title>基本情報</BasicInformation.Title> <BasicInformation.Subtitle>基本情報を入力してください</BasicInformation.Subtitle> <BasicInformation.NameInput /> <BasicInformation.FuriganaInput /> <BasicInformation.PostalCodeInput /> <BasicInformation.PrefectureSelect /> <BasicInformation.CityInput /> <BasicInformation.AddressInput /> <BasicInformation.PhoneInput /> <BasicInformation.SubmitButton>送信</BasicInformation.SubmitButton> </BasicInformation> ); }
function AdvancedBasicInformationForm() { return ( <BasicInformation sx={{ maxWidth: '800px', margin: '0 auto', background: 'linear-gradient(145deg, #f8fafc 0%, #f1f5f9 100%)', borderRadius: '20px', border: '1px solid #e2e8f0', }} onChange={(setError, getValues) => { const values = getValues(); if (!values.NameInput) { setError('NameInput', {message: '氏名は必須項目です', type: 'required'}); } if (values.PhoneInput && !/^[\d-+()]*$/.test(values.PhoneInput)) { setError('PhoneInput', {message: '有効な電話番号を入力してください', type: 'pattern'}); } }} onSubmit={formData => { console.log('フォームが送信されました:', formData); }} onInvalid={errors => { console.log('フォームバリデーションエラー:', errors); }} > {({defaultBlocks, defaultBlockOrder}) => { return { blocks: { ...defaultBlocks, title: { ...defaultBlocks.title, props: { ...defaultBlocks.title.props, sx: { fontSize: '2rem', fontWeight: 'bold', textAlign: 'center', marginBottom: '8px', background: 'linear-gradient(135deg, #0f172a, #1e293b)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text', }, children: 'プロフィール作成', }, }, subtitle: { ...defaultBlocks.subtitle, props: { ...defaultBlocks.subtitle.props, sx: {textAlign: 'center', color: '#64748b', marginBottom: '2rem'}, children: ( <div style={{display: 'flex', flexDirection: 'column', gap: '1rem'}}> <p>お客様の基本情報をご入力ください</p> <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px'}}> <div style={{display: 'flex', alignItems: 'center', gap: '4px'}}> <div style={{ width: '32px', height: '32px', backgroundColor: '#3b82f6', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '14px', fontWeight: '500', }} > 1 </div> <span style={{fontSize: '14px', fontWeight: '500', color: '#3b82f6'}}>基本情報</span> </div> <div style={{width: '48px', height: '2px', backgroundColor: '#cbd5e1'}}></div> <div style={{display: 'flex', alignItems: 'center', gap: '4px'}}> <div style={{ width: '32px', height: '32px', backgroundColor: '#cbd5e1', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#64748b', fontSize: '14px', fontWeight: '500', }} > 2 </div> <span style={{fontSize: '14px', color: '#64748b'}}>詳細設定</span> </div> </div> </div> ), }, }, nameInput: { ...defaultBlocks.nameInput, props: { ...defaultBlocks.nameInput.props, label: '氏名', placeholder: '例: 山田 太郎', sx: { '& .MuiOutlinedInput-root': { borderRadius: '10px', background: 'white', }, }, }, }, furiganaInput: { ...defaultBlocks.furiganaInput, props: { ...defaultBlocks.furiganaInput.props, label: 'フリガナ', placeholder: '例: ヤマダ タロウ', sx: { '& .MuiOutlinedInput-root': { borderRadius: '10px', background: 'white', }, }, }, }, submitButton: { ...defaultBlocks.submitButton, props: { ...defaultBlocks.submitButton.props, sx: { width: '100%', padding: '14px 32px', background: 'linear-gradient(135deg, #3b82f6, #2563eb)', borderRadius: '10px', fontWeight: 'bold', boxShadow: '0 8px 20px rgba(59, 130, 246, 0.3)', '&:hover': { background: 'linear-gradient(135deg, #2563eb, #1d4ed8)', boxShadow: '0 12px 25px rgba(59, 130, 246, 0.4)', }, }, children: '次のステップへ進む', }, }, }, blockOrder: defaultBlockOrder, }; }} </BasicInformation> ); }
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
onSubmit | (data: T) => void | 必須 | 有効なデータでフォームが送信されたときにトリガーされるコールバック関数 |
onChange | (setError, getValues) => void | 必須 | フォーム値が変更されたときにトリガーされるコールバック関数。バリデーション用のフォーム制御関数を提供 |
onInvalid | (errors: FieldErrors<T>) => void | 必須 | フォーム送信でバリデーションが失敗したときにトリガーされるコールバック関数 |
defaultValues | DefaultValues<T> | undefined | 初期レンダリング時にフィールドに設定するデフォルトフォーム値 |
children | BlocksOverride | undefined | デフォルトレンダリングをオーバーライドするカスタムブロックコンポーネント |
className | string | undefined | フォームコンテナスタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
spacing | number | 4 | 子要素間のスペーシング |
注意: このコンポーネントは component="form" を持つMUI StackProps<'form'> を拡張し、すべてのStackコンポーネントプロパティを継承します。
サブコンポーネント
BasicInformationコンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
BasicInformation.Title
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | "基本情報" | タイトルとして表示するコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
注意: このコンポーネントは variant="h4" と component="h2" を持つMUI TypographyProps を拡張します。
BasicInformation.Subtitle
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | "* は必須事項です" | サブタイトルとして表示するコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは variant="body2" を持つMUI TypographyProps を拡張します。
BasicInformation.NameInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "NameInput" | フォームデータ用のフィールド名 |
label | string | "氏名" | 入力フィールドのラベル |
placeholder | string | "氏名を入力" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
disabled | boolean | false | 入力が無効かどうか |
error | boolean | false | エラー状態を表示するかどうか |
helperText | string | undefined | 入力下に表示されるヘルパーテキスト |
fullWidth | boolean | true | 入力が全幅を占めるかどうか |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.FuriganaInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "FuriganaInput" | フォームデータ用のフィールド名 |
label | string | "フリガナ" | 入力フィールドのラベル |
placeholder | string | "フリガナを入力" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.PostalCodeInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PostalCodeInput" | フォームデータ用のフィールド名 |
label | string | "郵便番号" | 入力フィールドのラベル |
placeholder | string | "郵便番号を入力" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
inputMode | string | "numeric" | モバイルキーボード用の入力モード |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.PrefectureSelect
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PrefectureSelect" | フォームデータ用のフィールド名 |
label | string | "都道府県" | フィールドラベル |
placeholder | string | "都道府県を選択" | プレースホルダーテキスト |
options | Array<{value: string, label: string}> | PREFECTURES (47都道府県) | 都道府県オプションの配列 |
required | boolean | true | フィールドが必須かどうか |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI SelectProps を拡張します。
BasicInformation.CityInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "CityInput" | フォームデータ用のフィールド名 |
label | string | "市区町村" | 入力フィールドのラベル |
placeholder | string | "市区町村を入力" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.AddressInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "AddressInput" | フォームデータ用のフィールド名 |
label | string | "町名・番地・建物" | 入力フィールドのラベル |
placeholder | string | "町名・番地・建物を入力" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.PhoneInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PhoneInput" | フォームデータ用のフィールド名 |
label | string | "連絡先電話番号" | 入力フィールドのラベル |
placeholder | string | "電話番号を入力(ハイフンなしで入力)" | プレースホルダーテキスト |
required | boolean | true | フィールドが必須かどうか |
inputMode | string | "numeric" | モバイルキーボード用の入力モード |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
BasicInformation.SubmitButton
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | "次へ" | ボタンテキストコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
disabled | boolean | !formState.isValid | ボタンが無効かどうか |
variant | string | "contained" | MUI Buttonバリアント |
size | string | "large" | MUI Buttonサイズ |
type | string | "submit" | ボタンタイプ |
注意: このコンポーネントはMUI ButtonProps を拡張します。ボタンはフォームが無効な場合自動的に無効化されます。
BasicInformation.Input
カスタムフィールドを作成するための汎用入力コンポーネント。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | 必須 | フォームデータ用のフィールド名(フォームバインディングに必須) |
label | string | undefined | 入力フィールドのラベル |
placeholder | string | undefined | プレースホルダーテキスト |
required | boolean | false | フィールドが必須かどうか |
disabled | boolean | false | 入力が無効かどうか |
error | boolean | false | エラー状態を表示するかどうか |
helperText | string | undefined | 入力下に表示されるヘルパーテキスト |
fullWidth | boolean | true | 入力が全幅を占めるかどうか |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI TextFieldProps を拡張します。
🎨 設定例
カスタムフィールドラベル
<BasicInformation.NameInput
label="氏名"
placeholder="氏名を入力してください"
required={true}
/>
カスタム都道府県オプション
const customPrefectures = [
{value: 'tokyo', label: '東京都'},
{value: 'osaka', label: '大阪府'},
{value: 'kyoto', label: '京都府'},
];
<BasicInformation
onSubmit={data => console.log(data)}
onChange={() => {}}
onInvalid={errors => console.log(errors)}
>
<BasicInformation.Title>カスタム都道府県</BasicInformation.Title>
<BasicInformation.NameInput label="氏名" placeholder="氏名を入力してください" required={true} />
<BasicInformation.PrefectureSelect options={customPrefectures} placeholder="都道府県を選択してください" />
<BasicInformation.CityInput />
<BasicInformation.AddressInput />
<BasicInformation.SubmitButton
sx={{
background: 'linear-gradient(135deg, #3b82f6, #2563eb)',
borderRadius: '12px',
'&:hover': {
background: 'linear-gradient(135deg, #2563eb, #1d4ed8)',
},
}}
>
送信する
</BasicInformation.SubmitButton>
</BasicInformation>
スタイル付き送信ボタン
<BasicInformation.SubmitButton
sx={{
background: 'linear-gradient(135deg, #3b82f6, #2563eb)',
borderRadius: '12px',
'&:hover': {
background: 'linear-gradient(135deg, #2563eb, #1d4ed8)',
},
}}
>
送信する
</BasicInformation.SubmitButton>
ブロックオーバーライドパターン
<BasicInformation
onSubmit={data => console.log(data)}
onChange={() => {}}
onInvalid={errors => console.log(errors)}
>
{({defaultBlocks, defaultBlockOrder}) => ({
blocks: {
...defaultBlocks,
title: {
...defaultBlocks.title,
props: {
...defaultBlocks.title.props,
children: 'カスタムタイトル',
sx: {color: 'primary.main'},
},
},
// カスタムブロックを追加
customInfo: (
<div
style={{
padding: '12px 16px',
backgroundColor: '#e3f2fd',
borderRadius: '8px',
color: '#1976d2',
}}
>
すべてのフィールドは登録に必須です
</div>
),
},
blockOrder: [
'title',
'customInfo',
'subtitle',
...defaultBlockOrder.filter((k) => k !== 'title' && k !== 'subtitle'),
],
})}
</BasicInformation>
カスタム入力フィールドの追加
<BasicInformation
onSubmit={data => console.log(data)}
onChange={() => {}}
onInvalid={errors => console.log(errors)}
>
<BasicInformation.Title>拡張フォーム</BasicInformation.Title>
<BasicInformation.Subtitle />
<BasicInformation.NameInput />
<BasicInformation.Input name="CompanyName" label="会社名" placeholder="会社名を入力" required={false} />
<BasicInformation.PhoneInput />
<BasicInformation.SubmitButton />
</BasicInformation>
🔧 TypeScriptサポート
包括的な型定義による完全なTypeScriptサポート:
import {BasicInformation} from '@nodeblocks/frontend-basic-information-block';
import {DefaultValues, FieldErrors, UseFormGetValues, UseFormSetError} from 'react-hook-form';
// デフォルトフォームデータ構造
interface DefaultBasicInformationFormData {
NameInput: string;
FuriganaInput: string;
PostalCodeInput: string;
PrefectureSelect: string;
CityInput: string;
AddressInput: string;
PhoneInput: string;
}
// カスタムオプション用の選択オプション型
interface SelectOption {
value: string;
label: string;
}
const TypedBasicInformationExample = () => {
const handleSubmit = (formData: DefaultBasicInformationFormData): void => {
console.log('フォームが送信されました:', formData);
};
const handleInvalid = (errors: FieldErrors<DefaultBasicInformationFormData>): void => {
console.log('バリデーションエラー:', errors);
};
const handleChange = (
setError: UseFormSetError<DefaultBasicInformationFormData>,
getValues: UseFormGetValues<DefaultBasicInformationFormData>,
): void => {
const values = getValues();
// カスタムバリデーション
if (values.PhoneInput && values.PhoneInput.length < 10) {
setError('PhoneInput', {message: '電話番号が短すぎます'});
}
};
const defaultValues: DefaultValues<DefaultBasicInformationFormData> = {
NameInput: '山田太郎',
PrefectureSelect: '東京都',
};
return (
<BasicInformation<DefaultBasicInformationFormData>
onSubmit={handleSubmit}
onInvalid={handleInvalid}
onChange={handleChange}
defaultValues={defaultValues}
sx={{maxWidth: 600, mx: 'auto'}}
>
<BasicInformation.Title>基本情報</BasicInformation.Title>
<BasicInformation.Subtitle>詳細をご入力ください</BasicInformation.Subtitle>
<BasicInformation.NameInput />
<BasicInformation.FuriganaInput />
<BasicInformation.PostalCodeInput />
<BasicInformation.PrefectureSelect />
<BasicInformation.CityInput />
<BasicInformation.AddressInput />
<BasicInformation.PhoneInput />
<BasicInformation.SubmitButton>送信</BasicInformation.SubmitButton>
</BasicInformation>
);
};
📝 注意事項
- コンポーネントは
component="form"を持つMUIのStackコンポーネントをベースとして使用します - フォームバリデーションは
mode: 'onBlur'を持つreact-hook-formで処理されます - すべての入力フィールドは
Controllerを介してフォームコンテキストに自動的に接続されます - 送信ボタンは
formState.isValidがfalseの場合自動的に無効化されます - デフォルトブロック:
title、subtitle、nameInput、furiganaInput、postalCodeInput、prefectureSelect、cityInput、addressInput、phoneInput、submitButton、input PrefectureSelectコンポーネントはデフォルトで日本の47都道府県すべてを含みます- CSSクラスはBEMスタイルの命名に従います:
nbb-basic-information、nbb-basic-information-titleなど - 入力フィールドは内部でMUI
TextFieldを使用し、すべてのTextFieldプロパティをサポートします onChangeコールバックはリアルタイムバリデーションのためにフォーム値変更ごとにトリガーされます- デフォルトパディングは
p: 5(40px)、要素間スペーシングは4(32px)です
React、TypeScript、MUIを使用して❤️で構築されました。