パスワード変更ブロック
ChangePassword は MUI 上に構築された制御済みのパスワード変更フォームブロックです。
インストール
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-change-password-block
yarn add @nodeblocks/frontend-change-password-block
pnpm add @nodeblocks/frontend-change-password-block
bun add @nodeblocks/frontend-change-password-block
必要なもの
| 項目 | 重要な理由 |
|---|---|
data | フォーム state の単一の信頼できる情報源 (currentPassword, newPassword, confirmPassword) |
onDataChange | フィールド変更時に更新済み state とメタデータを受け取る。meta には name, value, cause (input, change, blur, clear, reset, programmatic), optional event が含まれます |
errors (optional) | フィールド単位のエラーフィードバックを表示する |
resetPasswordUrl (optional) | 「パスワードを忘れた」リンクの遷移先 URL |
ChangePassword はフォーム state を所有しません。state はアプリ側で保持し、data を通じて渡してください。
コード例
- Quick Start
- Labels and URLs
- Form Errors
- Compound Components
- Block Override
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} /> ); }
「パスワードを忘れた」URL とサブコンポーネントの文言をカスタマイズします。
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} resetPasswordUrl="/auth/resetpassword" onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > <ChangePassword.Title>パスワードを変更</ChangePassword.Title> <ChangePassword.Form> <ChangePassword.Form.CurrentPasswordField label="現在のパスワード" placeholder="現在のパスワードを入力" /> <ChangePassword.Form.ResetPasswordLink> <a href="#auth/resetpassword" style={{color: '#007ADD'}}> パスワードを忘れた方? </a> </ChangePassword.Form.ResetPasswordLink> <ChangePassword.Form.NewPasswordField label="新しいパスワード" placeholder="新しいパスワードを入力" /> <ChangePassword.Form.ConfirmPasswordField label="新しいパスワードを再入力" placeholder="新しいパスワードを再入力" /> <ChangePassword.Form.ChangePasswordButton>パスワードを変更</ChangePassword.Form.ChangePasswordButton> </ChangePassword.Form> </ChangePassword> ); }
ルートに labels prop はありません。ルートでは resetPasswordUrl を設定し、タイトル・フィールド・ボタンの文言はサブコンポーネントの props で上書きしてください。リンクのカスタムマークアップが必要な場合は ChangePassword.Form.ResetPasswordLink に children を渡してください。リンクのデフォルト文言は パスワードを忘れた方 です。
フォームを制御したまま、フィールドエラーを検証・表示します。
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); const [errors, setErrors] = React.useState({}); const handleDataChange = (nextData, meta) => { const {[meta.name]: _removed, ...restErrors} = errors; let nextErrors = restErrors; // Validate required fields on blur (same pattern as storybook) if (meta.cause === 'blur') { nextErrors = {...restErrors}; if (meta.name === 'currentPassword' && !nextData.currentPassword) { nextErrors.currentPassword = 'Current password is required.'; } if (meta.name === 'newPassword' && !nextData.newPassword) { nextErrors.newPassword = 'New password is required.'; } if (meta.name === 'confirmPassword') { if (!nextData.confirmPassword) { nextErrors.confirmPassword = 'Please confirm your new password.'; } else if (nextData.newPassword && nextData.confirmPassword !== nextData.newPassword) { nextErrors.confirmPassword = 'Passwords do not match.'; } } } setErrors(nextErrors); setData(nextData); }; return ( <ChangePassword data={data} errors={Object.keys(errors).length ? errors : undefined} onDataChange={handleDataChange} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} /> ); }
子ブロックを使って、制御された state の動作を保ちながらレイアウトをカスタマイズします。
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} resetPasswordUrl="/auth/resetpassword" onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > <ChangePassword.Title>パスワードを変更</ChangePassword.Title> <ChangePassword.Form> <ChangePassword.Form.CurrentPasswordField label="現在のパスワード" placeholder="現在のパスワードを入力" /> <ChangePassword.Form.ResetPasswordLink> <a href="#auth/resetpassword" style={{color: '#007ADD'}}> パスワードを忘れた方? </a> </ChangePassword.Form.ResetPasswordLink> <ChangePassword.Form.NewPasswordField label="新しいパスワード" placeholder="新しいパスワードを入力" /> <ChangePassword.Form.ConfirmPasswordField label="新しいパスワードを再入力" placeholder="新しいパスワードを再入力" /> <ChangePassword.Form.ChangePasswordButton>パスワードを変更</ChangePassword.Form.ChangePasswordButton> </ChangePassword.Form> </ChangePassword> ); }
関数 children を使ってデフォルトのブロックと順序を上書きします。
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > {({defaultBlocks, defaultBlockOrder}) => ({ blocks: { ...defaultBlocks, notice: ( <div style={{ background: '#eef4ff', border: '1px solid #cddcff', borderRadius: '8px', padding: '12px', fontSize: '14px', textAlign: 'center', width: '100%', maxWidth: 684, }} > 新しいパスワードに関するカスタム通知またはヘルプテキスト </div> ), }, blockOrder: ['notice', ...defaultBlockOrder], })} </ChangePassword> ); }
ブロックオーバーライドを使うタイミング
順序を変えたいとき、デフォルトの UI ブロックを置き換えたいとき、共有 state の処理を維持しながらカスタムコンテンツを挿入したいときにオーバーライドを使います。デフォルトの順序は title, form です。
重要な props
コア props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
data | ChangePasswordFormData ({ currentPassword?, newPassword?, confirmPassword? } or extended Record<string, unknown>) | Yes | - | 現在のフォーム data オブジェクト |
onDataChange | (data, meta) => void | Yes | - | 更新時に呼び出されます。meta には name, value, cause (input, change, blur, clear, reset, programmatic), optional event が含まれます |
errors | { [fieldName: string]: string | string[] } | No | undefined | data のフィールド名(currentPassword, newPassword, confirmPassword)に紐づくフィールドエラー |
コンテンツ props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
resetPasswordUrl | string | No | /auth/resetpassword | Form.ResetPasswordLink の URL(リンク文言のデフォルト: パスワードを忘れた方) |
レイアウトと構成 props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | BlocksOverride | ReactNode | No | undefined | デフォルトのブロックを上書きするか、カスタムの JSX children を提供します |
component | React.ElementType | No | 'form' | ルート要素の型 |
className | string | No | undefined | ルートコンテナのクラス名 |
sx | SxProps | No | undefined | ルートコンテナ向けの MUI システムスタイル |
ChangePassword は StackProps<'form'>(children を除く)も継承するため、onSubmit、id、noValidate などの標準的なフォーム props がサポートされます。オーバーライドなしのデフォルトのブロック順は title, form (defaultBlockOrder) です。
デフォルト UI ブロック
| Block | Built on | Notes |
|---|---|---|
ChangePassword (root) | Stack (component="form") | 制御されたフォームコンテナ。内部コンテンツの最大幅は 684px |
ChangePassword.Title | Typography | タイトル(variant="h6")。デフォルト パスワードを変更 |
ChangePassword.Form | Stack | フォームフィールドのコンテナ(送信はルート form が処理) |
ChangePassword.Form.CurrentPasswordField | TextField + IconButton | デフォルトのラベル/プレースホルダー 現在のパスワード / 現在のパスワードを入力 |
ChangePassword.Form.ResetPasswordLink | Box + Link | デフォルトのリンク文言 パスワードを忘れた方; href は resetPasswordUrl または /auth/resetpassword にフォールバック |
ChangePassword.Form.NewPasswordField | TextField + IconButton | デフォルト 新しいパスワード / 新しいパスワードを入力 |
ChangePassword.Form.ConfirmPasswordField | TextField + IconButton | デフォルト 新しいパスワードを再入力(ラベルとプレースホルダー) |
ChangePassword.Form.ChangePasswordButton | Button | 送信(variant="contained", type="submit")。デフォルト パスワードを変更 |
TypeScript
import {ChangePassword, ChangePasswordFormData} from '@nodeblocks/frontend-change-password-block';
type MyChangePasswordData = ChangePasswordFormData & {
userId?: string;
};