# PhoneInput

`PhoneInput`コンポーネントは、ユーザーフレンドリーな国際電話番号入力フィールドを提供します。`react-hook-form`とシームレスに統合され、国旗と国番号付きの検索可能な国選択機能、自動番号フォーマット、および`google-libphonenumber`による強力な検証機能を備えています。

このコンポーネントは、選択された国を共有フォームフィールドと同期させることで、[`CountrySelect`](./components-ui-form-elements-country-select.md)や[`AddressForm`](./components-ui-form-elements-address-form.md)などの他のフォーム要素と連携して動作するように設計されています。

## 仕組み

このコンポーネントは、`react-international-phone`ライブラリをコア機能として活用し、それをラップして`react-hook-form`およびMaterial-UIとの深い統合を提供します。ユーザーが国を選択したり番号を入力したりすると、コンポーネントはフォームの状態にある対応するフィールドを更新します。また、他のコンポーネントがフォーム内のリンクされた国フィールドを変更すると、自動的に国選択を更新します。

<!-- DIAGRAM_IMAGE_START:architecture:16:9:1764919317 -->
![PhoneInput](assets/diagram/phone-input-diagram-0.ja.jpg)
<!-- DIAGRAM_IMAGE_END -->

## Props

`PhoneInput`コンポーネントは、すべての標準的なMaterial-UIの`TextField` propsに加えて、以下の特定のpropsを受け入れます：

| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| `name` | `string` | Yes | - | `react-hook-form`に電話番号を登録するためのフィールド名。 |
| `countryFieldName` | `string` | No | `'billing_address.country'` | 選択された国のISO2コードを保存するフォームフィールドの名前。これにより、電話番号入力の国を、アドレスコンポーネントなど、フォームの他の部分と同期させることができます。 |

## 使用方法

`PhoneInput`コンポーネントを使用するには、`react-hook-form`の`FormProvider`でラップする必要があります。次の例は、検証機能を含む基本的な実装を示しています。

まず、ライブラリが提供する非同期検証関数が必要です。

```javascript phone-validator.js icon=logos:javascript
// src/libs/phone-validator.js
import { getPhoneUtil } from '@blocklet/payment-react/libs/phone-validator';

export const validatePhoneNumber = async (phoneNumber) => {
  if (!phoneNumber) return true;
  try {
    const util = await getPhoneUtil();
    const parsed = util.parseAndKeepRawInput(phoneNumber);
    return util.isValidNumber(parsed);
  } catch (err) {
    console.error('Phone validation error:', err);
    // ライブラリの読み込みに失敗した場合、単純な正規表現にフォールバックします
    const pattern = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/im;
    return pattern.test(phoneNumber) || 'Invalid phone number';
  }
};
```

これで、このバリデータをフォームコンポーネントで使用できます。

```jsx MyPaymentForm.tsx icon=logos:react
import { FormProvider, useForm } from 'react-hook-form';
import { Button, Box } from '@mui/material';
import { PhoneInput } from '@blocklet/payment-react';
import { validatePhoneNumber } from '../libs/phone-validator'; // 必要に応じてパスを調整してください

export default function MyPaymentForm() {
  const methods = useForm({
    mode: 'onBlur',
    defaultValues: {
      phone: '',
      'billing_address.country': 'us', // デフォルトの国
    },
  });

  const onSubmit = (data) => {
    alert(JSON.stringify(data, null, 2));
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Box display="flex" flexDirection="column" gap={2}>
          <PhoneInput
            label="Phone Number"
            name="phone"
            // フォームの状態にある国フィールドへのリンク
            countryFieldName="billing_address.country"
            // 検証ルールを追加
            rules={{
              validate: async (value) => {
                const isValid = await validatePhoneNumber(value);
                return isValid || 'Please enter a valid phone number.';
              },
            }}
            fullWidth
          />
          <Button type="submit" variant="contained">
            Submit
          </Button>
        </Box>
      </form>
    </FormProvider>
  );
}
```

### 解説

1.  **`FormProvider`**: `PhoneInput`を含むフォーム全体が`FormProvider`でラップされ、必要なフォームコンテキストを提供します。
2.  **`name="phone"`**: これにより、入力フィールドがフォームデータ内で`phone`という名前で登録されます。
3.  **`countryFieldName="billing_address.country"`**: これは`PhoneInput`に、フォームの状態にある`billing_address.country`フィールドの読み書きを両方行うように指示します。これにより同期が保たれます。このフィールドのデフォルト値は`useForm`で`'us'`に設定されています。
4.  **`rules`**: 非同期の`validate`関数を`rules` propに渡します。`react-hook-form`は検証中にこの関数が解決されるのを待ちます。チェックを実行するために`validatePhoneNumber`ユーティリティが呼び出されます。

## AddressFormとの統合

`PhoneInput`の真価は、`AddressForm`と併用することで発揮されます。両方のコンポーネントは同じ国フィールド（デフォルトでは`billing_address.country`）にリンクできるため、`AddressForm`で国を変更すると、`PhoneInput`の国旗と国番号が自動的に更新されます。

この統合の完全な例については、[`AddressForm`](./components-ui-form-elements-address-form.md)のドキュメントを参照してください。