Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 1 addition & 17 deletions docs/hooks/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ The shape of `data` varies by hook — see each hook's reference page for detail

Hooks let you declare which form fields are required beyond the built-in defaults. Each hook has built-in requiredness rules based on the form mode (create vs. update), and you can override optional fields to be required.

The API varies by hook. Some hooks use `requiredFields` (flat array or per-mode object), while newer hooks use `optionalFieldsToRequire` with type-safe, mode-aware overrides derived from the schema configuration.
The API varies by hook. Some hooks use `requiredFields` (flat array or per-mode object), while newer hooks use `optionalFieldsToRequire` with type-safe, mode-aware overrides.

### `requiredFields` (useEmployeeDetailsForm, useWorkAddressForm)

Expand Down Expand Up @@ -847,19 +847,3 @@ Use this when you need to:
- Access form state like `isDirty`, `isValid`, or `dirtyFields`

In most cases the built-in Fields, `onSubmit`, and `getFormSubmissionValues` are sufficient. Reach for `hookFormInternals` only when you need fine-grained form control that the hook doesn't expose directly.

---

## Advanced: Fields Metadata

Each hook exposes `form.fieldsMetadata` — an object keyed by field name with metadata about each field's current state. The field components consume this automatically under the hood to determine required/disabled states and populate select options, so you typically don't need to interact with it directly.

If you're building fully custom field UI, you can read this metadata yourself:

```tsx
const { fieldsMetadata } = employeeDetails.form

if (fieldsMetadata.email.isRequired) {
// Show a required indicator in your custom UI
}
```
42 changes: 21 additions & 21 deletions docs/hooks/useCompensationForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,35 @@ import { useCompensationForm, SDKFormProvider } from '@gusto/embedded-react-sdk'

### Configurable Required Fields

The compensation schema declares requiredness rules per field. Fields default to **always required** unless configured otherwise:

| Field | Rule | Required on create | Required on update | Partner-configurable? |
| ----------------------- | ---------- | ------------------ | ------------------ | --------------------- |
| `jobTitle` | `'create'` | Yes | No | Yes (on update) |
| `flsaStatus` | `'create'` | Yes | No | Yes (on update) |
| `paymentUnit` | `'create'` | Yes | No | Yes (on update) |
| `rate` | `'create'` | Yes | No | Yes (on update) |
| `startDate` | `'create'` | Yes | No | Yes (on update) |
| `adjustForMinimumWage` | (unlisted) | Yes | Yes | No |
| `stateWcCovered` | (unlisted) | Yes | Yes | No |
| `twoPercentShareholder` | (unlisted) | Yes | Yes | No |
| `minimumWageId` | predicate | When toggle is on | When toggle is on | No |
| `stateWcClassCode` | predicate | When WC is covered | When WC is covered | No |

`optionalFieldsToRequire` lets you override fields that are **optional** in a given mode to be required. The type is derived from the schema configuration:
Each compensation field has a default required-ness based on form mode (create vs. update). Fields default to **always required** unless configured otherwise:

| Field | Required on create | Required on update | Partner-configurable? |
| ----------------------- | ------------------ | ------------------ | --------------------- |
| `jobTitle` | Yes | No | Yes (on update) |
| `flsaStatus` | Yes | No | Yes (on update) |
| `paymentUnit` | Yes | No | Yes (on update) |
| `rate` | Yes | No | Yes (on update) |
| `startDate` | Yes | No | Yes (on update) |
| `adjustForMinimumWage` | Yes | Yes | No |
| `stateWcCovered` | Yes | Yes | No |
| `twoPercentShareholder` | Yes | Yes | No |
| `minimumWageId` | When toggle is on | When toggle is on | No |
| `stateWcClassCode` | When WC is covered | When WC is covered | No |

`optionalFieldsToRequire` lets you override fields that are **optional** in a given mode to be required. TypeScript constrains which fields can be promoted per mode:

```typescript
type CompensationOptionalFieldsToRequire = {
create?: never[] // all 'create' fields are already required on create
create?: never[] // these fields are already required on create
update?: Array<'jobTitle' | 'flsaStatus' | 'paymentUnit' | 'rate' | 'startDate'>
}
```

Only the `update` key is useful for compensation — it lets you require fields in update mode that would otherwise be optional. The `create` key has no configurable fields because all `'create'`-scoped fields are already required on create.
Only the `update` key is useful for compensation — it lets you require fields in update mode that would otherwise be optional. The `create` key has no configurable fields because every field listed above is already required on create.

`startDate` requirements are ignored when `withStartDateField` is `false` (the field is excluded from the schema entirely).
`startDate` requirements are ignored when `withStartDateField` is `false` (the field is omitted from the form entirely).

Cross-field validations (`minimumWageId` when `adjustForMinimumWage` is `true`, workers' comp fields in WA) are always enforced by the schema regardless of `optionalFieldsToRequire`.
Cross-field rules (`minimumWageId` when `adjustForMinimumWage` is `true`, workers' comp fields in WA) are always enforced regardless of `optionalFieldsToRequire`.

```tsx
useCompensationForm({
Expand Down Expand Up @@ -312,7 +312,7 @@ This field is automatically **disabled** when the FLSA status is Commission Only
validationMessages={{
REQUIRED: 'Amount is a required field',
RATE_MINIMUM: 'Amount must be at least $1.00',
RATE_EXEMPT_THRESHOLD: `FLSA Exempt employees must meet salary threshold of $${FLSA_OVERTIME_SALARY_LIMIT}/year`,
RATE_EXEMPT_THRESHOLD: 'FLSA Exempt employees must meet salary threshold of $35,568/year',
}}
/>
```
Expand Down
6 changes: 3 additions & 3 deletions docs/hooks/useEmployeeDetailsForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const EmployeeDetailsErrorCodes = {

### Fields.FirstName

Text input for the employee's first name. Validates against `NAME_REGEX` to reject special characters.
Text input for the employee's first name. Validates that the value contains only allowed name characters (letters, spaces, hyphens, and apostrophes).

| Prop | Type | Required |
| -------------------- | -------------------------------------------- | -------- |
Expand Down Expand Up @@ -208,7 +208,7 @@ No validation codes — this field is always optional.

### Fields.LastName

Text input for the employee's last name. Validates against `NAME_REGEX` to reject special characters.
Text input for the employee's last name. Validates that the value contains only allowed name characters (letters, spaces, hyphens, and apostrophes).

| Prop | Type | Required |
| -------------------- | -------------------------------------------- | -------- |
Expand Down Expand Up @@ -310,7 +310,7 @@ Text input for the employee's Social Security number. Automatically formats inpu
| ------------- | -------------------------------------------- |
| `INVALID_SSN` | Value does not match the expected SSN format |

The `fieldsMetadata.ssn.hasRedactedValue` flag indicates whether the employee already has an SSN on file. When `true`, the field renders with a masked placeholder (e.g., `•••-••-1234`). If the field is included in `requiredFields` but `hasSsn` is already `true` on the employee, the requirement is automatically waived.
The masked placeholder appears as `•••-••-1234`. When the employee already has an SSN on record, the `REQUIRED` rule is automatically waived even if `ssn` is listed in `requiredFields`.

```tsx
<Fields.Ssn
Expand Down
2 changes: 1 addition & 1 deletion docs/hooks/useFederalTaxesForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Updates an employee's federal tax (W-4) withholding information — filing statu
import { useFederalTaxesForm, SDKFormProvider } from '@gusto/embedded-react-sdk'
```

The federal tax record is created automatically with the employee, so this hook is always in update mode. Only the revised 2020 W-4 format (`rev_2020_w4`) is supported for updates.
The federal tax record is created automatically with the employee, so this hook is always in update mode. Only the revised 2020 W-4 format is supported for updates.

---

Expand Down
4 changes: 2 additions & 2 deletions docs/hooks/usePayScheduleForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { usePayScheduleForm, SDKFormProvider } from '@gusto/embedded-react-sdk'

### Configurable Required Fields

The `optionalFieldsToRequire` prop lets you override optional fields to be required in a given mode. Only fields with `'never'` requiredness rules are configurable:
The `optionalFieldsToRequire` prop lets you override optional fields to be required in a given mode. Only fields that are optional by default can be promoted to required:

```tsx
usePayScheduleForm({
Expand All @@ -39,7 +39,7 @@ usePayScheduleForm({
})
```

`customTwicePerMonth` is the only field configurable via `optionalFieldsToRequire`. All other fields use either `'always'` requiredness or conditional predicate rules that are not partner-configurable.
`customTwicePerMonth` is currently the only field configurable via `optionalFieldsToRequire`. All other fields are either always required or have conditional rules that are not partner-configurable.

### PayScheduleFormData

Expand Down
22 changes: 11 additions & 11 deletions docs/hooks/useWorkAddressForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ import { useWorkAddressForm, SDKFormProvider } from '@gusto/embedded-react-sdk'

`useWorkAddressForm` accepts a single options object:

| Prop | Type | Required | Default | Description |
| ------------------------ | ------------------------------------------------------------------------------------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `companyId` | `string` | Yes | — | The UUID of the company. Used to fetch available locations. |
| `employeeId` | `string` | Yes | — | The UUID of the employee. For composed create flows where the id isn't known until a prior form submits, pass `''` here and supply the real id at submit time via `WorkAddressSubmitOptions.employeeId`. |
| `workAddressUuid` | `string` | No | — | When set, the form loads that row via GET `/v1/work_addresses/{work_address_uuid}` and the hook is in update mode. When omitted, the hook is in create mode (POST). Use `useCurrentWorkAddressForm` to auto-resolve the employee's active row. |
| `withEffectiveDateField` | `boolean` | No | `true` | Whether to include the effective date field. When `false`, pass effective date via `onSubmit` options instead. |
| `requiredFields` | `WorkAddressField[] \| { create?: WorkAddressField[], update?: WorkAddressField[] }` | No | — | Additional fields to make required beyond API defaults. A flat array applies to both modes; an object targets specific modes. |
| `defaultValues` | `Partial<WorkAddressFormData>` | No | — | Pre-fill form values. Server data takes precedence when editing an existing work address. |
| `validationMode` | `'onSubmit' \| 'onBlur' \| 'onChange' \| 'onTouched' \| 'all'` | No | `'onSubmit'` | When validation runs. Passed through to react-hook-form. |
| `shouldFocusError` | `boolean` | No | `true` | Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler`. |
| Prop | Type | Required | Default | Description |
| ------------------------ | ------------------------------------------------------------------------------------ | -------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `companyId` | `string` | Yes | — | The UUID of the company. Used to fetch available locations. |
| `employeeId` | `string` | Yes | — | The UUID of the employee. For composed create flows where the id isn't known until a prior form submits, pass `''` here and supply the real id at submit time via `WorkAddressSubmitOptions.employeeId`. |
| `workAddressUuid` | `string` | No | — | When set, the hook is in update mode and loads that work address row. When omitted, the hook is in create mode. Use `useCurrentWorkAddressForm` to auto-resolve the employee's active row. |
| `withEffectiveDateField` | `boolean` | No | `true` | Whether to include the effective date field. When `false`, pass effective date via `onSubmit` options instead. |
| `requiredFields` | `WorkAddressField[] \| { create?: WorkAddressField[], update?: WorkAddressField[] }` | No | — | Additional fields to make required beyond API defaults. A flat array applies to both modes; an object targets specific modes. |
| `defaultValues` | `Partial<WorkAddressFormData>` | No | — | Pre-fill form values. Server data takes precedence when editing an existing work address. |
| `validationMode` | `'onSubmit' \| 'onBlur' \| 'onChange' \| 'onTouched' \| 'all'` | No | `'onSubmit'` | When validation runs. Passed through to react-hook-form. |
| `shouldFocusError` | `boolean` | No | `true` | Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler`. |

### WorkAddressField

Expand Down Expand Up @@ -108,7 +108,7 @@ The hook returns a discriminated union on `isLoading`.

### Mode detection

The hook is in update mode when `workAddressUuid` is provided (the row is fetched via GET `/v1/work_addresses/{work_address_uuid}`) and in create mode otherwise.
The hook is in update mode when `workAddressUuid` is provided and in create mode otherwise.

### Submit callbacks

Expand Down
Loading