Basic Information Block
The BasicInformation Component is a fully customizable and accessible form for collecting user's basic information built with React and TypeScript. It provides a complete address and contact information interface with modern design patterns, form validation, and flexible customization options.
๐ Installationโ
npm install @nodeblocks/frontend-basic-information-block@0.1.7
๐ Usageโ
import {BasicInformation} from '@nodeblocks/frontend-basic-information-block';
- Basic Usage
- Advanced Usage
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>
);
}
๐ง Props Referenceโ
Main Component Propsโ
The main BasicInformation component inherits all props from the HTML form element (except onSubmit, onChange, and children which are overridden) and adds:
| 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 |
Sub-Componentsโ
The BasicInformation component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
BasicInformation.Titleโ
Inherits all props from the HTML h2 element and adds:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "ๅบๆฌๆ
ๅ ฑ" | Content to display as the title |
BasicInformation.Subtitleโ
Inherits all props from the HTML div element and adds:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default required fields message | Content to display as the subtitle - typically shows required field information |
BasicInformation.NameInputโ
Uses deepMerge to combine default field options with passed props. Inherits all props from the internal Input component and adds:
| 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 |
Note: This component additional inherits some common HTML input element props.
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 |
Note: This component additional inherits some common HTML input element props.
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 |
Note: This component additional inherits some common HTML input element props.
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 |
Note: This component additional inherits some common HTML select element props.
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 |
Note: This component additional inherits some common HTML input element props.
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 |
Note: This component additional inherits some common HTML input element props.
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 |
Note: This component additional inherits some common HTML input element props.
BasicInformation.SubmitButtonโ
Inherits all props from the Button component from @basaldev/blocks-frontend-framework and adds:
| 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) |
Note: This component additional inherits some common HTML button element props.
Additional Field Componentsโ
The component also provides additional field types that can be used in custom forms:
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 Supportโ
Full TypeScript support with comprehensive type definitions:
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>
);
};
Built with โค๏ธ using React, TypeScript, and modern web standards.