基本情報ブロック
BasicInformationコンポーネントは、ReactとTypeScriptで構築された、ユーザーの基本情報を収集するための完全にカスタマイズ可能でアクセシブルなフォームです。モダンなデザインパターン、フォームバリデーション、柔軟なカスタマイズオプションを備えた完全な住所と連絡先情報のインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-basic-information-block@0.1.7
📖 使用方法
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
style={{maxWidth: '1000px', margin: '0 auto'}}
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,
style: {
fontSize: '2rem',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '8px',
background: 'linear-gradient(135deg, #3B82F6, #8B5CF6)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text',
},
children: 'プロフィール作成',
},
},
subtitle: {
...defaultBlocks.subtitle,
props: {
...defaultBlocks.subtitle.props,
style: {textAlign: 'center', color: '#6B7280', 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: '#D1D5DB'}}></div>
<div style={{display: 'flex', alignItems: 'center', gap: '4px'}}>
<div
style={{
width: '32px',
height: '32px',
backgroundColor: '#D1D5DB',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#6B7280',
fontSize: '14px',
fontWeight: '500',
}}
>
2
</div>
<span style={{fontSize: '14px', color: '#6B7280'}}>詳細設定</span>
</div>
<div style={{width: '48px', height: '2px', backgroundColor: '#D1D5DB'}}></div>
<div style={{display: 'flex', alignItems: 'center', gap: '4px'}}>
<div
style={{
width: '32px',
height: '32px',
backgroundColor: '#D1D5DB',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#6B7280',
fontSize: '14px',
fontWeight: '500',
}}
>
3
</div>
<span style={{fontSize: '14px', color: '#6B7280'}}>完了</span>
</div>
</div>
</div>
),
},
},
nameInput: {
...defaultBlocks.nameInput,
props: {
...defaultBlocks.nameInput.props,
label: '氏名',
placeholder: '例: 山田 太郎',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
furiganaInput: {
...defaultBlocks.furiganaInput,
props: {
...defaultBlocks.furiganaInput.props,
label: 'フリガナ',
placeholder: '例: ヤマダ タロウ',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
postalCodeInput: {
...defaultBlocks.postalCodeInput,
props: {
...defaultBlocks.postalCodeInput.props,
label: '郵便番号',
placeholder: '例: 123-4567',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
prefectureSelect: {
...defaultBlocks.prefectureSelect,
props: {
...defaultBlocks.prefectureSelect.props,
label: '都道府県',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
selectOptionValues: [
{value: 'tokyo', label: '東京都'},
{value: 'osaka', label: '大阪府'},
{value: 'kanagawa', label: '神奈川県'},
{value: 'saitama', label: '埼玉県'},
{value: 'chiba', label: '千葉県'},
],
},
},
cityInput: {
...defaultBlocks.cityInput,
props: {
...defaultBlocks.cityInput.props,
label: '市区町村',
placeholder: '例: 渋谷区',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
addressInput: {
...defaultBlocks.addressInput,
props: {
...defaultBlocks.addressInput.props,
label: '町名・番地・建物',
placeholder: '例: 道玄坂1-2-3 ビル名 4階',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '24px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
phoneInput: {
...defaultBlocks.phoneInput,
props: {
...defaultBlocks.phoneInput.props,
label: '連絡先電話番号',
placeholder: '例: 03-1234-5678',
style: {
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '12px',
border: '2px solid #e2e8f0',
padding: '16px',
marginBottom: '32px',
transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
},
},
},
submitButton: {
...defaultBlocks.submitButton,
props: {
...defaultBlocks.submitButton.props,
style: {
width: '100%',
padding: '16px 32px',
background: 'linear-gradient(135deg, #3B82F6, #8B5CF6)',
color: 'white',
fontWeight: 'bold',
borderRadius: '12px',
border: 'none',
boxShadow: '0 10px 25px rgba(0, 0, 0, 0.15)',
transition: 'all 0.2s ease',
cursor: 'pointer',
},
onMouseEnter: e => {
e.target.style.background = 'linear-gradient(135deg, #2563EB, #7C3AED)';
e.target.style.transform = 'translateY(-2px)';
e.target.style.boxShadow = '0 15px 35px rgba(0, 0, 0, 0.2)';
},
onMouseLeave: e => {
e.target.style.background = 'linear-gradient(135deg, #3B82F6, #8B5CF6)';
e.target.style.transform = 'translateY(0)';
e.target.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.15)';
},
children: (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px'}}>
<span>次のステップへ進む</span>
<svg style={{width: '20px', height: '20px'}} fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</div>
),
},
},
},
blockOrder: defaultBlockOrder,
};
}}
</BasicInformation>
);
}
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
メインの BasicInformation コンポーネントはHTML form 要素からすべてのプロパティを継承し(onSubmit、onChange、children はオーバーライドされます)、以下を追加します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
onSubmit | (data: T) => void | 必須 | 有効なデータでフォームが送信されたときにトリガーされるコールバック関数 |
onChange | (setError, getValues) => void | 必須 | フォーム値が変更されたときにトリガーされるコールバック関数。バリデーション用のフォーム制御関数を提供 |
onInvalid | (errors: FieldErrors<T>) => void | 必須 | フォーム送信でバリデーションが失敗したときにトリガーされるコールバック関数 |
defaultValues | DefaultValues<T> | undefined | 初期レンダリング時にフィールドに設定するデフォルトフォーム値 |
children | BlocksOverride | undefined | デフォルトレンダリングをオーバーライドするカスタムブロックコンポーネント |
className | string | undefined | フォームコンテナスタイリング用の追加CSSクラス名 |
サブコンポーネント
BasicInformationコンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
BasicInformation.Title
HTML h2 要素からすべてのプロパティを継承し、以下を追加します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | "基本情報" | タイトルとして表示するコンテンツ |
BasicInformation.Subtitle
HTML div 要素からすべてのプロパティを継承し、以下を追加します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | デフォルトの必須フィールドメッセージ | サブタイトルとして表示するコンテンツ - 通常は必須フィールド情報を表示 |
BasicInformation.NameInput
deepMerge を使用してデフォルトフィールドオプションと渡されたプロパティを結合します。内部の Input コンポーネントからすべてのプロパティを継承し、以下を追加します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "NameInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "氏名" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.FuriganaInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "FuriganaInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "フリガナ" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.PostalCodeInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PostalCodeInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "郵便番号" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.PrefectureSelect
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PrefectureSelect" | フォームデータ用のフィールド名 |
label | string | "都道府県" | フィールドラベル |
labelWeight | enum | "bold" | ラベルの太さ |
selectOptionValues | Array<{value: string, label: string}> | [] | 都道府県オプションの配列 |
isRequired | boolean | undefined | フィールドが必須かどうか |
isDisabled | boolean | undefined | 入力が無効かどうか |
errorText | string | undefined | 入力用のエラーテキスト |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは一般的なHTML select 要素プロパティも追加で継承します。
BasicInformation.CityInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "CityInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "市区町村" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.AddressInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "AddressInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "町名・番地・建物" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.PhoneInput
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "PhoneInput" | フォームデータ用のフィールド名 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | "連絡先電話番号" | 入力フィールドのラベル |
labelWeight | enum | "bold" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
inputMode | string | "numeric" | モバイルキーボード用の入力モード |
注意: このコンポーネントは一般的なHTML input 要素プロパティも追加で継承します。
BasicInformation.SubmitButton
@basaldev/blocks-frontend-framework の Button コンポーネントからすべてのプロパティを継承し、以下を追加します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | "次へ" | ボタン内に配置するテキスト |
className | string | undefined | スタイリング用の追加CSSクラス名 |
fill | enum | "fill" | ボタンの塗りつぶしスタイル |
icon | enum | undefined | ボタン左側のオプションアイコン |
iconColor | enum | undefined | 左側アイコンの色。指定しない場合、塗りつぶしタイプに応じたデフォルト色が使用されます。 |
isDisabled | boolean | false | ボタンが無効で使用できないかどうか |
onClick | function | undefined | ボタンクリックを処理する関数 |
size | enum | "M" | ボタンの垂直サイズ |
textAlign | enum | "center" | ボタン内のアイコンとテキストの配置 |
textColor | enum | "default" | ボタンテキストの色 |
textEmphasis | boolean | false | ボタンテキストの太さ |
textSize | enum | "M" | ボタンテキストのサイズ |
type | enum | "submit" | ボタンの目的(HTMLタイプに影響) |
注意: このコンポーネントは一般的なHTML button 要素プロパティも追加で継承します。
追加フィールドコンポーネント
コンポーネントはカスタムフォームで使用できる追加のフィールドタイプも提供します:
BasicInformation.Input
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | 必須 | フォームデータ用のフィールド名 |
errorText | string | undefined | 入力用のエラーテキスト |
isDisabled | boolean | undefined | 入力が無効かどうか |
isRequired | boolean | undefined | 入力が必須かどうか |
label | string | 必須 | 入力フィールドのラベル |
labelWeight | enum | "regular" | ラベルの太さ |
onOperationClick | () => void | undefined | 操作onClickコールバック |
postfixText | string | undefined | コンポーネントの後に配置するテキスト |
showPassword | boolean | undefined | パスワードを表示するかどうか |
🔧 TypeScript サポート
包括的な型定義による完全なTypeScriptサポート:
import {BasicInformation} from '@nodeblocks/frontend-basic-information-block';
// 将来的にはreact-hook-formを使用せず、独自のフォーム処理を使用する予定です
import {FieldErrors, UseFormGetValues, UseFormSetError} from 'react-hook-form';
// デフォルトフォームデータ構造
interface DefaultBasicInformationFormData {
NameInput: string;
FuriganaInput: string;
PostalCodeInput: string;
PrefectureSelect: string;
CityInput: string;
AddressInput: string;
PhoneInput: string;
}
// カスタムフィールドで拡張(コンポーネントはユニオン型を使用)
const MyBasicInformationForm = () => {
const handleSubmit = (formData: DefaultBasicInformationFormData) => {
console.log('フォームが送信されました:', formData);
// フォーム送信を処理
};
const handleInvalid = (errors: FieldErrors<DefaultBasicInformationFormData>) => {
console.log('バリデーションエラー:', errors);
// バリデーションエラーを処理
};
const handleChange = (
setError: UseFormSetError<DefaultBasicInformationFormData>,
getValues: UseFormGetValues<DefaultBasicInformationFormData>,
) => {
const values = getValues();
// カスタムバリデーション
if (values.PhoneInput && values.PhoneInput.length < 10) {
setError('PhoneInput', {message: '電話番号が短すぎます'});
}
};
return (
<BasicInformation<DefaultBasicInformationFormData>
onSubmit={handleSubmit}
onInvalid={handleInvalid}
onChange={handleChange}
defaultValues={{NameInput: '山田太郎'}}>
<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>
);
};
React、TypeScript、モダンなウェブ標準を使用して❤️で構築されました。