基本情報ブロック
BasicInformationコンポーネントは、ReactとTypeScriptで構築された、ユーザーの基本情報を収集するための完全にカスタマイズ可能でアクセシブルなフォームです。モダンなデザインパターン、フォームバリデーション、柔軟なカスタマイズオプションを備えた完全な住所と連絡先情報のインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-basic-information-block
📖 使用方法
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、モダンなウェブ標準を使用して❤️で構築されました。