Skip to main content

useSplitPaymentsForm

useSplitPaymentsForm(props: UseSplitPaymentsFormProps): UseSplitPaymentsFormResult

Headless React Hook Form hook for splitting an employee's Direct Deposit across multiple bank accounts.

Remarks​

Supports two split modes: Percentage (whole-number shares that sum to 100) and Amount (dollar amounts, with the last-priority split absorbing the remainder). Always operates in update mode against the employee's existing payment method.

The Percentage sum-to-100 invariant is surfaced via status.hasPercentageImbalance (not as a per-field error). With the default validationMode: 'onSubmit', the imbalance flag appears after the first failed Save and clears live as the user corrects the total.

Example​

Example
import {
useSplitPaymentsForm,
SDKFormProvider,
type SplitByValue,
type UseSplitPaymentsFormReady,
} from '@gusto/embedded-react-sdk'

function SplitPaycheckScreen({ employeeId }: { employeeId: string }) {
const splitForm = useSplitPaymentsForm({ employeeId })

if (splitForm.isLoading) return null
return <SplitPaycheckReady splitForm={splitForm} />
}

function SplitPaycheckReady({ splitForm }: { splitForm: UseSplitPaymentsFormReady }) {
const { Fields } = splitForm.form
const { hasPercentageImbalance, percentageTotal } = splitForm.status

return (
<SDKFormProvider formHookResult={splitForm}>
<form
onSubmit={e => {
e.preventDefault()
void splitForm.actions.onSubmit()
}}
>
{hasPercentageImbalance && (
<div role="alert">Splits must total 100%. Currently {percentageTotal}%.</div>
)}
<Fields.SplitBy label="Split by" getOptionLabel={(value: SplitByValue) => value} />
{Fields.splits.map(split => (
<split.Field
key={split.uuid}
label={split.name ?? 'Account'}
min={0}
/>
))}
<button type="submit" disabled={splitForm.status.isPending}>Save</button>
</form>
</SDKFormProvider>
)
}

Props​

UseSplitPaymentsFormProps​

Props for useSplitPaymentsForm.

PropertyTypeDescription
employeeIdstringEmployee whose payment splits are being edited.
optionalFieldsToRequire?SplitPaymentsFormOptionalFieldsToRequireOverride optional fields to be required. Currently a no-op — splitBy and priority are always required, and per-split splitAmount required-ness is automatic.
shouldFocusError?booleanAuto-focus the first invalid field on submit. Set to false when using composeSubmitHandler. Defaults to true.
validationMode?"all" | "onChange" | "onBlur" | "onSubmit" | "onTouched"When validation runs. Passed through to react-hook-form. Defaults to 'onSubmit'.

Returns​

UseSplitPaymentsFormResult

A loading-state result while the payment method and bank accounts are loading, or a UseSplitPaymentsFormReady once ready.

UseSplitPaymentsFormResult​

UseSplitPaymentsFormResult = HookLoadingResult | UseSplitPaymentsFormReady

Return type of useSplitPaymentsForm — a discriminated union on isLoading.


UseSplitPaymentsFormReady​

Ready-state return value of useSplitPaymentsForm.

PropertyTypeDescription
actionsobjectActions that mutate the form or submit it.
actions.onSubmit() => Promise<HookSubmitResult<EmployeePaymentMethod> | undefined>Submit the form. Returns the updated payment method on success or undefined on validation/mutation failure.
actions.reorderSplits(orderedUuids: string[]) => voidReorder splits by uuid (Amount mode). Pass the ordered list of split uuids; the last uuid becomes the remainder. The hook writes the new priority map and re-anchors the remainder's splitAmount to null (clearing the previous remainder to 0).
dataobjectServer-fetched data and derived working values.
data.bankAccountsEmployeeBankAccount[]All bank accounts available to allocate splits across.
data.paymentMethodEmployeePaymentMethodThe employee's current payment method.
data.remainderIdstringUUID of the split that absorbs the remainder in Amount mode (always the last by priority).
data.splitsWorkingSplit[]The current working split entries, one per bank account.
errorHandlingHookErrorHandlingError state and recovery actions.
formobjectForm bindings: pre-bound field components, per-field metadata, submission values, and react-hook-form internals.
form.FieldsSplitPaymentsFormFields-
form.fieldsMetadataSplitPaymentsFormFieldsMetadata-
form.getFormSubmissionValues() => SplitPaymentsFormData | undefined-
form.hookFormInternalsHookFormInternals<SplitPaymentsFormData>-
isLoadingfalseAlways false in this branch; discriminates from HookLoadingResult.
statusobjectSubmission state and reactive form-level flags.
status.hasPercentageImbalancebooleantrue after a failed Percentage-mode Save when the splits don't sum to 100; clears live as the user corrects the total. Follows the standard react-hook-form validation lifecycle (controlled by validationMode). Only surfaces in Percentage mode.
status.isPendingbooleantrue while the update mutation is in flight.
status.mode"update"Always 'update' — the hook always edits an existing payment method.
status.percentageTotalnumberLive sum of splitAmount values; useful for displaying the current total in Percentage mode.
status.splitBy"Percentage" | "Amount"Current splitBy value, reactively tracked.

Fields​

SplitPaymentsFormFields​

Field components exposed by useSplitPaymentsForm on form.Fields.

PropertyTypeDescription
SplitByComponentType<SplitByFieldProps>Radio group bound to splitBy; selects Percentage or Amount split mode.
splitsSplitFieldEntry[]One entry per bank account, each carrying a pre-bound Field component for the per-split amount.

SplitBy​

Radio group bound to splitBy; selects Percentage or Amount split mode.

<form.Fields.SplitBy
label="Split by"
validationMessages={{ REQUIRED: '…' }}
/>

SplitByFieldProps​

HookFieldProps<RadioGroupHookFieldProps<SplitPaymentsFormRequiredValidation, SplitByValue>>

Props accepted by useSplitPaymentsForm's Fields.SplitBy component.

PropertyTypeDescription
labelstringVisible label rendered above the field.
FieldComponent?ComponentType<RadioGroupProps>Replaces the default radio group UI component; must accept the same props as RadioGroupProps.
getOptionLabel?(entry: SplitByValue) => stringMaps a raw option entry to its display label; when omitted, options use the labels provided by the hook.
validationMessages?ValidationMessages<SplitPaymentsFormRequiredValidation>Custom error text keyed by validation error code.

Also accepts description, formHookResult from RadioGroupHookFieldProps.


splits​

One entry per bank account, each carrying a pre-bound Field component for the per-split amount.

{form.Fields.splits.map(entry => (
<entry.Field
key={entry.uuid}
label={entry.name ?? '…'}
validationMessages={{
REQUIRED: '…',
INVALID_AMOUNT: '…',
INVALID_PERCENTAGE: '…',
}}
/>
))}

SplitFieldEntry​

Single per-account entry surfaced on form.Fields.splits. Each entry carries identifying metadata for the underlying bank account plus the bound Field component for its split amount.

PropertyTypeDescription
FieldComponentType<SplitFieldProps>Bound Field component for this split's amount input.
hiddenAccountNumberstring | nullLast-four masking string for the bank account number, when available.
namestring | nullDisplay name of the bank account, when available.
uuidstringBank account uuid that this split targets.

SplitFieldProps​

Props accepted by a bound split-amount Field exposed on form.Fields.splits[i].Field. The Field is pre-bound to its split; it formats values as currency in Amount mode and as a percentage in Percentage mode. The remainder split is auto-disabled and treated as not required by the hook; the rest are required.

PropertyTypeDescription
labelstringLabel shown above the input.
description?ReactNodeOptional descriptive text rendered below the label.
FieldComponent?ComponentType<NumberInputProps>Override the rendered number input component.
formHookResult?FormHookResultPass-through of the parent form hook result for cross-field validation context.
max?string | numberForwarded to the underlying number input.
min?string | numberForwarded to the underlying number input.
placeholder?stringForwarded to the underlying number input.
validationMessages?ValidationMessages<SplitFieldValidation>Override the default localized validation message(s).

Validations​

SplitPaymentsFormRequiredValidation​

SplitPaymentsFormRequiredValidation = "REQUIRED"

Validation error codes emitted by useSplitPaymentsForm fields that only emit REQUIRED.

Utility types​

SPLIT_BY_VALUES​

const SPLIT_BY_VALUES: readonly ["Percentage", "Amount"]

Supported split-by modes: split by percentage of net pay, or by fixed dollar amount per account.


SplitByValue​

SplitByValue = "Percentage" | "Amount"

Union of split-by mode values that the form accepts.


SplitFieldValidation​

SplitFieldValidation = typeof SplitPaymentsFormErrorCodes.REQUIRED | typeof SplitPaymentsFormErrorCodes.INVALID_AMOUNT | typeof SplitPaymentsFormErrorCodes.INVALID_PERCENTAGE

Validation codes a bound split-amount Field can emit at submit time: REQUIRED (every non-remainder split must have a value), INVALID_AMOUNT (Amount mode, value < 0), INVALID_PERCENTAGE (Percentage mode, non-integer or out of 0..100). Supply translations for all three via validationMessages. The sum-to-100 invariant is surfaced separately via status.hasPercentageImbalance.


SplitPaymentsFormData​

SplitPaymentsFormData = object

Shape of the values managed by the split payments form. splitAmount and priority are keyed by bank account uuid.

Properties​

PropertyTypeDescription
priorityRecord<string, number>Per-account priority values keyed by bank account uuid; the highest priority receives the remainder.
splitAmountRecord<string, number | null>Per-account split values keyed by bank account uuid (percent or dollars depending on splitBy).
splitBySplitByValueSelected split mode — by percentage or by fixed amount.

SplitPaymentsFormErrorCode​

SplitPaymentsFormErrorCode = "REQUIRED" | "INVALID_PERCENTAGE" | "INVALID_AMOUNT" | "DUPLICATE_PRIORITIES" | "PERCENTAGE_TOTAL_MISMATCH"

Union of validation error code strings emitted by the split payments form schema.


SplitPaymentsFormErrorCodes​

const SplitPaymentsFormErrorCodes: object

Validation error codes emitted by the split payments form schema. Map these codes to localized copy in validationMessages when composing the hook.

Type Declaration​

NameType
DUPLICATE_PRIORITIES"DUPLICATE_PRIORITIES"
INVALID_AMOUNT"INVALID_AMOUNT"
INVALID_PERCENTAGE"INVALID_PERCENTAGE"
PERCENTAGE_TOTAL_MISMATCH"PERCENTAGE_TOTAL_MISMATCH"
REQUIRED"REQUIRED"

SplitPaymentsFormField​

SplitPaymentsFormField = "priority" | "splitBy" | "splitAmount"

Field names accepted by the split payments form.


SplitPaymentsFormFieldsMetadata​

Per-field metadata exposed on form.fieldsMetadata for useSplitPaymentsForm.

Remarks​

The three named fields are always present. In addition, one dynamic entry is keyed by full form path per split — splitAmount.<bankAccountUuid> — so the number and identity of those keys depend on the employee's bank accounts at runtime.

Indexable​

[key: `splitAmount.${string}`]: FieldMetadata

Properties​

PropertyTypeDescription
priorityFieldMetadataThe priority container field.
splitAmountFieldMetadataThe splitAmount container field. Per-split values live at splitAmount.<uuid>.
splitByFieldMetadataWithOptions<"Percentage" | "Amount">Split mode selector (by percentage or by fixed amount).

SplitPaymentsFormOptionalFieldsToRequire​

SplitPaymentsFormOptionalFieldsToRequire = OptionalFieldsToRequire<typeof requiredFieldsConfig>

Keys of optional split payments fields that can be promoted to required via the hook's optionalFieldsToRequire option.


WorkingSplit​

A single split entry — pairs a bank account identifier with its current split allocation.

Remarks​

Surfaced on data.splits from useSplitPaymentsForm. Derived from paymentMethod.splits when present, otherwise from the employee's bank accounts (one entry per account, no allocated amount). Carries the raw domain data — use it for label construction or lookups by uuid.

Properties​

PropertyTypeDescription
hiddenAccountNumberstring | nullMasked account number suffix, when available.
namestring | nullAccount nickname, when available.
prioritynumberOrdering value — splits are processed in ascending priority; the highest priority is the remainder.
splitAmountnumber | nullAllocation amount — null for the remainder split in Amount mode and for splits that haven't been allocated yet.
uuidstringUUID of the underlying bank account.

Endpoints​