# Field Library

URL: https://docs.forms.saastro.io/docs/library
> Ready-to-use semantic fields — full name, email, phone, consent… — with validators and translations baked in. Define a field once, reuse it everywhere.

# Field Library

`FIELD_REGISTRY` describes field *types* (text, email, select…) with type-level defaults. The **field library** is one level up: a curated set of **fully-configured semantic fields** — `Full name`, `Email`, `Phone`, `Consent`, `Country`… — each shipping its label, placeholder, serializable validators, and translations. Drop one into a form and you get the config **and** its translations in a single step, instead of re-wiring "email + required + format" every time.

It lives in its own lean subpath so it never weighs on the root bundle:

```ts
```

---

## What's in the box

24 fields, grouped for discovery. Each one carries a serializable `schema` (compiled to Zod at runtime) and a Spanish (`es`) translation overlay on top of the English base config.

| Key                | Type       | Group     | Validators                          |
| ------------------ | ---------- | --------- | ----------------------------------- |
| `fullName`         | `text`     | personal  | required, minLength 2               |
| `firstName`        | `text`     | personal  | required, minLength 1               |
| `lastName`         | `text`     | personal  | required, minLength 1               |
| `age`              | `number`   | personal  | required, min 0, max 120, integer   |
| `address`          | `text`     | personal  | —                                   |
| `country`          | `select`   | personal  | required (12 countries, translated) |
| `birthdate`        | `date`     | personal  | required                            |
| `postalCode`       | `text`     | personal  | maxLength 12                        |
| `email`            | `email`    | contact   | required, format email              |
| `phone`            | `phone`    | contact   | required                            |
| `message`          | `textarea` | contact   | required, maxLength 1000            |
| `company`          | `text`     | commerce  | —                                   |
| `website`          | `url`      | commerce  | format url                          |
| `serviceType`      | `select`   | commerce  | required (Design/Dev/Consulting/…)  |
| `budgetRange`      | `select`   | commerce  | required (budget brackets)          |
| `projectDetails`   | `textarea` | commerce  | required, minLength 20              |
| `consent`          | `checkbox` | survey    | required, mustBeTrue (terms)        |
| `marketingConsent` | `checkbox` | survey    | required, mustBeTrue (marketing)    |
| `eventAttendance`  | `radio`    | survey    | required (yes/no/maybe, translated) |
| `guestCount`       | `number`   | survey    | min 1, max 10, integer              |
| `dietaryNotes`     | `textarea` | survey    | —                                   |
| `dsaRequestType`   | `select`   | survey    | required (GDPR rights, translated)  |
| `requestDetails`   | `textarea` | survey    | —                                   |
| `identityDeclaration` | `checkbox` | survey | required, mustBeTrue                |

---

## An entry's shape

```ts
interface FieldLibraryEntry {
  /** The complete field config — base (English) strings + serializable validators. */
  fieldConfig: FieldConfig;
  /** Display name in the builder palette. */
  label: string;
  /** Optional lucide icon name; defaults to the field type's icon. */
  icon?: string;
  /** Short description for the palette tooltip. */
  description?: string;
  /** Grouping: 'personal' | 'contact' | 'commerce' | 'survey'. */
  group: 'personal' | 'contact' | 'commerce' | 'survey';
  /** Translations keyed by locale. The base config is the default language. */
  i18n?: Record<string, FieldLibraryI18n>;
}
```

The base config is written in English; `i18n.es` overlays the Spanish strings (the same shape as a [`LocaleOverlay`](/docs/i18n) field entry — `label`, `placeholder`, `helperText`, `description`, `options`). For example:

```ts
FIELD_LIBRARY.email = {
  label: 'Email',
  group: 'contact',
  icon: 'Mail',
  description: 'Email address with format validation',
  fieldConfig: {
    type: 'email',
    label: 'Email',
    placeholder: 'you@example.com',
    schema: { required: true, format: 'email' },
  },
  i18n: { es: { label: 'Correo electrónico', placeholder: 'tucorreo@ejemplo.com' } },
};
```

---

## Using a library field

### In a config

Spread the entry's `fieldConfig` under whatever name you want. Because `schema` is a serializable [`ValidationRules`](/docs/validation) object, the validators come along automatically:

```ts

const config: FormConfig = {
  formId: 'contact',
  fields: {
    email: FIELD_LIBRARY.email.fieldConfig,
    message: FIELD_LIBRARY.message.fieldConfig,
  },
  steps: { main: { title: 'Contact', fields: ['email', 'message'] } },
  buttons: { submit: { type: 'submit', label: 'Send' } },
};
```

### Bringing the translations along

A library field's `i18n` overlay is keyed by locale; re-key it under the field name and merge it into the form's `i18n.translations` so the field renders translated when `config.locale` is set (see [Internationalization](/docs/i18n)):

```ts
const entry = FIELD_LIBRARY.email;

const config: FormConfig = {
  formId: 'contact',
  fields: { email: entry.fieldConfig },
  steps: { main: { title: 'Contact', fields: ['email'] } },
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    translations: {
      es: { fields: { email: entry.i18n!.es } },
    },
  },
  locale: 'es', // renders "Correo electrónico"
};
```

### Grouped, for a picker

`getFieldLibraryByGroup()` returns the entries bucketed by `group` — handy for rendering a categorized palette:

```ts

const byGroup = getFieldLibraryByGroup();
// { personal: [...], contact: [...], commerce: [...], survey: [...] }
```

---

## In the visual builder

The [form builder](https://forms.saastro.io) surfaces the library in two places:

- **Library** section of the field palette — drag `Email`, `Full name`, `Country`… onto a step. The field lands fully configured, and its bundled translation is merged into the form's `i18n` automatically (so it shows no "untranslated" ⚠ in that language).
- **Save to library** — configure any field, then save it as a reusable entry of your own. Your fields live in the browser (`localStorage`) and appear in the same Library section under *My fields*, draggable just like the built-ins.

---

## See also

- [Validation](/docs/validation) — the `ValidationRules` each entry's `schema` uses.
- [Internationalization](/docs/i18n) — the overlay model the bundled translations plug into.
- [FormBuilder](/docs/formbuilder) — the fluent API for assembling forms.
