# ElvixLegalEntities

> Single-frame multi-step wizard for legal entities (individual, sole prop, company) with VAT live-validation and tap-to-edit.

<!-- app/account/legal-entities/page.tsx -->
```tsx
"use client";

import { ElvixLegalEntities } from "@elvix.is/sdk/react";

export function LegalEntitiesPane() {
  return (
    <ElvixLegalEntities
      width={420}
      height={580}
      onChange={(entities) => {
        // Re-read the entity you want to invoice from after every save.
        const primary = entities[0];
        console.log("primary legal entity:", primary?.id);
      }}
      onResult={(r) => {
        if (!r.ok) return console.warn(r.error, r.message);
        console.log(`legal entities now holds ${r.count} records`);
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `height` | `number` | optional | `580` | Fixed frame height in pixels. When omitted the frame clamps to `min(540px, 66dvh)` so it never overflows shorter viewports. |
| `width` | `number \| string` | optional | `"100%"` | Frame width. Pass a number for fixed pixels, a string for any CSS width. |
| `onChange` | `(entities: LegalEntityRecord[]) => void` | optional | — | Fires after every successful save or delete with the full list of rows. Use this to refresh host summaries or pick a default for invoicing. |
| `onResult` | `(result: ElvixLegalEntitiesResult) => void` | optional | — | Terminal callback for every attempt. Safe payload only: `{ ok: true, count }` or `{ ok: false, error, message }`. Never carries the entity rows. |

> **Note:** Detail rows are tap-to-edit. Tapping any field on the detail view re-enters the matching pane with the row prefilled and switches the terminal confirm from POST to PATCH. The full lifecycle (add, edit, delete, set default) runs inside the frame, the SDK never navigates the host.

> **Warning:** `onResult` never carries the entity rows. If you need the actual records (for an invoicing dropdown, a server sync, anything), read them from `onChange(entities)` instead. The split is deliberate: `onResult` is the safe analytics hook, `onChange` is the data hook.


## Related

- [ElvixAddressBook](/docs/components/elvix-address-book.md): Single-frame wizard for billing or shipping addresses with Google Places search, default toggle, and tap-to-edit.
- [ElvixRegion](/docs/components/elvix-region.md): Single-frame wizard for the user's regional preferences singleton: country cascade plus tap-to-edit on every derived field.
