基本情報ブロック
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('Form values:', getValues());
const values = getValues();
if (!values.NameInput) {
setError('NameInput', {message: 'Name is required', type: 'required'});
}
}}
onSubmit={formData => {
console.log('Form submitted:', formData);
}}
onInvalid={errors => {
console.log('Form validation errors:', errors);
}}>
<BasicInformation.Title>Basic Information</BasicInformation.Title>
<BasicInformation.Subtitle>Please fill in your basic information</BasicInformation.Subtitle>
<BasicInformation.NameInput />
<BasicInformation.FuriganaInput />
<BasicInformation.PostalCodeInput />
<BasicInformation.PrefectureSelect />
<BasicInformation.CityInput />
<BasicInformation.AddressInput />
<BasicInformation.PhoneInput />
<BasicInformation.SubmitButton>Submit</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('Form submitted:', formData);
}}
onInvalid={errors => {
console.log('Form validation errors:', 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 は上書きされます)、さらに次を追加します:
| Prop | Type | Default | Description |
|---|---|---|---|
onSubmit | (data: T) => void | Required | Callback function triggered when form is submitted with valid data |
onChange | (setError, getValues) => void | Required | Callback function triggered when form values change. Provides form control functions for validation |
onInvalid | (errors: FieldErrors<T>) => void | Required | Callback function triggered when form submission fails validation |
defaultValues | DefaultValues<T> | undefined | Default form values to populate fields on initial render |
children | BlocksOverride | undefined | Custom block components to override default rendering |
className | string | undefined | Additional CSS class name for styling the form container |
サブコンポーネント
BasicInformation コンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントはメインコンポーネントのコンテキストからデフォルト値を受け取り、props でそれらを上書きできます。
BasicInformation.Title
HTML h2 要素のすべてのプロパティを継承し、さらに次を追加します:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "基本情報" | Content to display as the title |
BasicInformation.Subtitle
HTML div 要素のすべてのプロパティを継承し、さらに次を追加します:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default required fields message | Content to display as the subtitle - typically shows required field information |
BasicInformation.NameInput
deepMerge を使ってデフォルトのフィールド設定と渡された props を結合します。内部の Input コンポーネントのすべての props を継承し、さらに次を追加します:
| Prop | Type | Default | Description |
|------|------|---------|-------------|s
| name | string | "NameInput" | Field name for form data |
| className | string | undefined | Additional CSS class name for styling |
| errorText | string | undefined | Error text for the input |
| isDisabled | boolean | undefined | Whether the input is disabled |
| isRequired | boolean | undefined | Whether the input is required |
| label | string | "氏名" | Label of the input field |
| labelWeight | enum | "bold" | Label weight |
| onOperationClick | () => void | undefined | Operation onClick callback |
| postfixText | string | undefined | Text to place after the component |
| showPassword | boolean | undefined | Whether to show password |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.FuriganaInput
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "FuriganaInput" | Field name for form data |
className | string | undefined | Additional CSS class name for styling |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "フリガナ" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.PostalCodeInput
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "PostalCodeInput" | Field name for form data |
className | string | undefined | Additional CSS class name for styling |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "郵便番号" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.PrefectureSelect
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "PrefectureSelect" | Field name for form data |
label | string | "都道府県" | Field label |
labelWeight | enum | "bold" | Label weight |
selectOptionValues | Array<{value: string, label: string}> | [] | Array of prefecture options |
isRequired | boolean | undefined | Whether the field is required |
isDisabled | boolean | undefined | Whether the input is disabled |
errorText | string | undefined | Error text for the input |
className | string | undefined | Additional CSS class name for styling |
注: このコンポーネントは、いくつかの共通 HTML select 要素プロパティも追加で継承します。
BasicInformation.CityInput
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "CityInput" | Field name for form data |
className | string | undefined | Additional CSS class name for styling |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "市区町村" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.AddressInput
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "AddressInput" | Field name for form data |
className | string | undefined | Additional CSS class name for styling |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "町名・番地・建物" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.PhoneInput
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "PhoneInput" | Field name for form data |
className | string | undefined | Additional CSS class name for styling |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "連絡先電話番号" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
inputMode | string | "numeric" | Input mode for mobile keyboards |
注: このコンポーネントは、いくつかの共通 HTML input 要素プロパティも追加で継承します。
BasicInformation.SubmitButton
@basaldev/blocks-frontend-framework の Button コンポーネントのすべての props を継承し、さらに次を追加します:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "次へ" | Text to place inside the button |
className | string | undefined | Additional CSS class name for styling |
fill | enum | "fill" | Button fill style |
icon | enum | undefined | Optional icon for the left-hand side of the button |
iconColor | enum | undefined | Color for the left-hand side icon. When not provided, a default color for the fill type will be used. |
isDisabled | boolean | false | Whether the button is disabled and cannot be used |
onClick | function | undefined | Function to handle button click |
size | enum | "M" | Button vertical size |
textAlign | enum | "center" | Button icon and text positioning within the button |
textColor | enum | "default" | Button text color |
textEmphasis | boolean | false | Button text weight |
textSize | enum | "M" | Button text size |
type | enum | "submit" | Button purpose (affects html type) |
注: このコンポーネントは、いくつかの共通 HTML button 要素プロパティも追加で継承します。
追加フィールドコンポーネント
このコンポーネントは、カスタムフォームで使用できる追加のフィールドタイプも提供します:
BasicInformation.Input
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | Required | Field name for form data |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | Required | Label of the input field |
labelWeight | enum | "regular" | Label weight |
onOperationClick | () => void | undefined | Operation onClick callback |
postfixText | string | undefined | Text to place after the component |
showPassword | boolean | undefined | Whether to show password |
🔧 TypeScript サポート
包括的な型定義を備えた完全な TypeScript サポート:
import {BasicInformation} from '@nodeblocks/frontend-basic-information-block';
//in future we will not use react-hook-form, we will use our own form handling
import {FieldErrors, UseFormGetValues, UseFormSetError} from 'react-hook-form';
// Default form data structure
interface DefaultBasicInformationFormData {
NameInput: string;
FuriganaInput: string;
PostalCodeInput: string;
PrefectureSelect: string;
CityInput: string;
AddressInput: string;
PhoneInput: string;
}
// Extend with custom fields (component uses union type)
const MyBasicInformationForm = () => {
const handleSubmit = (formData: DefaultBasicInformationFormData) => {
console.log('Form submitted:', formData);
// Handle form submission
};
const handleInvalid = (errors: FieldErrors<DefaultBasicInformationFormData>) => {
console.log('Validation errors:', errors);
// Handle validation errors
};
const handleChange = (
setError: UseFormSetError<DefaultBasicInformationFormData>,
getValues: UseFormGetValues<DefaultBasicInformationFormData>,
) => {
const values = getValues();
// Custom validation
if (values.PhoneInput && values.PhoneInput.length < 10) {
setError('PhoneInput', {message: 'Phone number too short'});
}
};
return (
<BasicInformation<DefaultBasicInformationFormData>
onSubmit={handleSubmit}
onInvalid={handleInvalid}
onChange={handleChange}
defaultValues={{NameInput: 'John Doe'}}>
<BasicInformation.Title>Basic Information</BasicInformation.Title>
<BasicInformation.Subtitle>Please provide your details</BasicInformation.Subtitle>
<BasicInformation.NameInput />
<BasicInformation.FuriganaInput />
<BasicInformation.PostalCodeInput />
<BasicInformation.PrefectureSelect />
<BasicInformation.CityInput />
<BasicInformation.AddressInput />
<BasicInformation.PhoneInput />
<BasicInformation.SubmitButton>Submit</BasicInformation.SubmitButton>
</BasicInformation>
);
};
React、TypeScript、そして最新の Web 標準で構築されています。