# Form Elements

The `@blocklet/payment-react` library provides a collection of granular input components designed to simplify the creation of custom payment and contact information forms. These elements are built with validation and user experience in mind, integrating smoothly with `react-hook-form` to provide a robust and flexible solution for data collection.

Each component is designed to be a self-contained unit, allowing you to compose them into complex forms tailored to your specific requirements. Below is an overview of the available form elements.

<x-cards data-columns="2">
  <x-card data-title="AddressForm" data-icon="lucide:map-pin" data-href="/components/ui/form-elements/address-form">
    A pre-built form for collecting billing address details with country-specific validation.
  </x-card>
  <x-card data-title="PhoneInput" data-icon="lucide:phone" data-href="/components/ui/form-elements/phone-input">
    An international phone number input with an integrated country code selector and validation.
  </x-card>
  <x-card data-title="CountrySelect" data-icon="lucide:globe" data-href="/components/ui/form-elements/country-select">
    A searchable dropdown for selecting a country, complete with flags and a mobile-friendly UI.
  </x-card>
  <x-card data-title="CurrencySelector" data-icon="lucide:coins" data-href="/components/ui/form-elements/currency-selector">
    A component that allows users to choose their preferred payment currency from available options.
  </x-card>
</x-cards>

## Common Usage Pattern

These form elements are intended to be used within a `FormProvider` from `react-hook-form`. You can compose them to build comprehensive forms that capture all the necessary information for a transaction. While each component has its own set of properties, they share a common integration pattern.

Here is a basic example of how you might combine several form elements to create a user information form:

```jsx MyCustomForm.tsx icon=logos:react
import { FormProvider, useForm } from 'react-hook-form';
import { AddressForm, PhoneInput, CurrencySelector } from '@blocklet/payment-react';
import { Button, Stack } from '@mui/material';

// Assume `availableCurrencies` is fetched from your backend
const availableCurrencies = [
  {
    id: 'usd_xxx',
    name: 'USD',
    symbol: 'USD',
    logo: 'url/to/usd_logo.png',
    method: { id: 'stripe', name: 'Stripe' },
  },
  // ... other currencies
];

function MyCustomForm() {
  const methods = useForm({
    defaultValues: {
      currency: 'usd_xxx',
      phone_number: '',
      billing_address: {
        line1: '',
        city: '',
        state: '',
        postal_code: '',
        country: 'US', // Use ISO2 code
      },
    },
  });

  const onSubmit = (data) => {
    console.log('Form data submitted:', data);
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Stack spacing={2}>
          <CurrencySelector
            value={methods.watch('currency')}
            currencies={availableCurrencies}
            onChange={(currencyId) => methods.setValue('currency', currencyId)}
          />
          <PhoneInput name="phone_number" label="Phone Number" required />
          <AddressForm mode="required" stripe={false} />
          <Button type="submit" variant="contained">
            Submit
          </Button>
        </Stack>
      </form>
    </FormProvider>
  );
}
```

In this example, `CurrencySelector`, `PhoneInput`, and `AddressForm` are combined within a single form. `CurrencySelector` is used as a controlled component tied to the form's state, while `PhoneInput` and `AddressForm` are uncontrolled components that automatically register their fields and validation rules with the `react-hook-form` context.

## Next Steps

To learn more about the specific properties and implementation details of each component, please explore their individual documentation pages. 

Start with the [AddressForm](./components-ui-form-elements-address-form.md) to see how to collect billing information.