import { type HTMLAttributes, type ReactNode } from 'react'; import { type UsePasswordRequirementsOptions } from '../../components/password-input'; import { type SelectOption } from '../../components/select'; import { type BrandMarkMotion } from '../_shared/brand-mark'; import { type RegistrationFieldVerification, type RegistrationVerifiableField } from './use-contact-verification'; /** The fields of the form, in the order they appear. */ export declare const REGISTRATION_FORM_FIELDS: readonly ["firstName", "lastName", "email", "emailConfirm", "password", "passwordConfirm", "phone", "branch", "terms"]; export type RegistrationFormField = (typeof REGISTRATION_FORM_FIELDS)[number]; /** The fields built on `TextInput`, which can refuse paste or copy. */ export type RegistrationFormTextField = Extract; /** What `onSubmit` receives once every check has passed. A field the * form does not show is empty (`''`, or `false` for the terms). */ export interface RegistrationFormValues { firstName: string; lastName: string; email: string; /** As typed. It matches `email` apart from case and outer spaces. */ emailConfirm: string; password: string; /** Equal to `password` when the confirm field is shown. */ passwordConfirm: string; /** In E.164 form, e.g. `+393331234567`. */ phone: string; /** The chosen `branches` value. */ branch: string; /** True when the terms are shown: the form does not submit without. */ terms: boolean; /** The reCAPTCHA token, when the host passes `recaptchaSiteKey`. */ captchaToken?: string; } /** Values to show when the form opens. There is no password here, on * purpose: a password is never sent back to the browser. */ export type RegistrationFormInitialValues = Partial>; /** * What the development shortcut puts in the fields. Unlike * `initialValues` it may carry a password: the host passes it only in * development, from its own server, and the kit holds no test data of * its own. */ export type RegistrationFormDevValues = Partial>; /** The development-only shortcut at the top right of the card. */ export interface RegistrationFormDevBypass { /** What the shortcut does: the button's name and tooltip. */ label: string; /** * The values to put in the fields when the button is pressed, as if * typed: the checks, the password checklist and the posted values all * see them. The confirm fields are filled from the same values, so * they match. A field the form does not show is ignored, and a * read-only email is kept. */ values?: RegistrationFormDevValues; /** * True to submit the form right after filling it, through the normal * path: the checks still run, reCAPTCHA still runs, a native form * still posts. Default false: fill only. */ submit?: boolean; /** Called after filling, for a host with a route of its own. */ onClick?: () => void; } /** Messages from the server, already translated by the host: one per * field, plus `form` for a message about the whole form. */ export type RegistrationFormErrors = Partial>; /** The data behind the existing-account state of `RegistrationForm`. */ export interface RegistrationFormExistingAccount { /** Where "Sign in" goes. Same tab. An unsafe address is dropped. */ loginHref: string; /** Where "Reset password" goes. Optional. Same tab. An unsafe address is dropped. */ resetPasswordHref?: string; } /** The host's own form field names, for a native form post. `captcha` * names the hidden field that carries the reCAPTCHA token. */ export type RegistrationFormFieldNames = Partial>; export interface RegistrationFormProps extends Omit, 'title' | 'onSubmit'> { /** Replaces the heading "Create your account". Pass it translated. */ title?: string; /** A line under the heading, e.g. "No installation needed". Pass it * translated. */ description?: string; /** The heading's level. Default 2, for a page that has its own `h1`. */ headingLevel?: 1 | 2 | 3; /** * Shows the Alfadocs mark above the heading, with the heading and its * line centred under it. Default true. With `false` the heading sits * at the start edge, for a host that shows its own logo beside the * card. */ showLogo?: boolean; /** * How the mark arrives when the card opens: its pieces come together * (`assemble`, the default), it turns once (`spin`), it beats * (`pulse`), or it is still (`none`). It plays once and rests, and * holds still under reduced motion and in the accessible themes. */ logoMotion?: BrandMarkMotion; /** * Host content between the heading and the fields, such as a notice * or a list of benefits. It sits outside the form, so nothing in it is * posted. Keep any heading inside it below the card's own level. */ children?: ReactNode; /** * A short notice above the fields, as plain text already translated. It * shows as an info alert, quiet to screen readers (it is not news). For * a server-rendered page that can only pass JSON. Comes before * `benefits` and `children`. */ notice?: string; /** * What the person gets, one short line each, already translated. They * show as a compact list with a tick. Comes after `notice` and before * `children`. */ benefits?: string[]; /** * The fields to show. Default: all of them, which is the doctor form. * A patient form is `['email', 'password', 'passwordConfirm', 'terms']`. * Leave out `emailConfirm` or `passwordConfirm` to drop that confirm * field. The list picks fields, it does not order them; email and * password always show; `branch` also needs `branches`. */ fields?: readonly RegistrationFormField[]; /** Values to show when the form opens, such as the email from an * invite link. Read once. Never a password. */ initialValues?: RegistrationFormInitialValues; /** * Messages from the server, already translated. Each shows on its * field until the user changes that field; `form` shows above the * fields, as does a message for a field the form does not show. * * Messages present when the form opens (a page the server rendered * after a failed post) take focus: the error summary at the top of the * form, which lists each field with a message, or the message above the * fields when no field has one. * * On a React host, when the messages change, both password fields * are emptied and focus moves as above. Set `submitting` while you * send: the form then also notices an answer that says the same as * the last one (another address, also taken), which the messages * alone cannot show. Any object works, kept in state or rebuilt on * each render (`errors={{ email: emailError }}`). */ errors?: RegistrationFormErrors; /** * Shows the email from `initialValues` read-only, for a person invited * with an address they cannot change here. Off by default: choose it * only when the server will refuse any other address. The value is * still posted and still read out, there is no confirm email field, * and the browser does not check it. Ignored when there is no initial * email, so the field is never both empty and locked. */ emailReadOnly?: boolean; /** A line under the email field, e.g. "You can change it later in the * settings". Pass it translated. */ emailDescription?: string; /** * Fields that refuse paste and drop, so the user types them, e.g. * `['passwordConfirm']`. Default: none. Autofill from the browser or a * password manager still works. A refused paste is announced and shown * under the field. The host decides: see the docs for the WCAG * position, which differs between the email and password fields. */ blockPaste?: readonly RegistrationFormTextField[]; /** * Fields that refuse copy, cut and dragging text out. Default: none. * Browsers already refuse to copy from a password field while it is * hidden. See the docs for the WCAG position. */ blockCopy?: readonly RegistrationFormTextField[]; /** The specialities to choose from. The field shows, and is required, * only when this has entries. */ branches?: SelectOption[]; /** * The password rules, shown as a live checklist. Keep them equal to * the server's. Default: 12 characters with an uppercase letter, a * lowercase letter and a number, counting only `A-Z`, `a-z` and `0-9` * (`charset: 'ascii'`), which is the platform's rule. */ passwordPolicy?: UsePasswordRequirementsOptions; /** * Where "terms of use" leads. A path on the same site, or an address * written in full (`https://…`). Anything else, such as an address * that would lead off the site without saying so, shows the words * without a link. */ termsHref?: string; /** Where "privacy policy" leads. Same rule as `termsHref`. */ privacyHref?: string; /** * Replaces the sentence beside the terms box ("I accept the terms of * use and the privacy policy") with the host's own wording and links, * already translated. The legal wording is the host's to choose. When * set, `termsHref` and `privacyHref` are not used. The box stays * required. */ termsLabel?: ReactNode; /** * `termsLabel` as a string, for a host that can only pass JSON. Already * translated. Mark the links with `…` and * `…`: they lead to `termsHref` and `privacyHref` * (new tab; without a safe address, the words show without a link). * Any other tag shows its text only. No marker: plain text. Ignored * when `termsLabel` is set. */ termsLabelText?: string; /** A line shown with the terms box and read out with it, e.g. "We * will not send you any advertising". Pass it translated. */ termsDescription?: ReactNode; /** `termsDescription` as a string, with the same markers as * `termsLabelText`. Ignored when `termsDescription` is set. */ termsDescriptionText?: string; /** Adds "Already have an account? Sign in". Same rule as `termsHref`. */ loginHref?: string; /** * The server refused the email because an account already has it. The email * field shows the kit's own message, naming the way forward, with a link to * sign in and a link to reset the password. Data only, so it works from JSON. * * The state is read against the email the form opened with * (`initialValues.email`, which must not be empty), so it is for a page the * server renders again after refusing the post. A React host that answers * through `onSubmit` mounts the form again (a new `key`) with * `initialValues.email` set to the refused address. Any edit to the email * removes the message and the links; typing the opening address back brings * them back. While it shows, the card's footer sign-in line is hidden, so * there is one "Sign in". * * Privacy: an address in a link's URL lands in server logs and in analytics * page URLs. Preferred: keep the address in the host's own session and link * plainly (`/login`). Allowed: put it in the query string * (`/login?email=...`). */ existingAccount?: RegistrationFormExistingAccount; /** A Google reCAPTCHA v2 site key of the invisible type. The check * runs when the user submits. Leave it out where the server does not * verify a token. */ recaptchaSiteKey?: string; /** Replaces the button's "Create account". Pass it translated. */ submitLabel?: string; /** True while the host sends the values: the button shows a spinner * and a second submit is ignored. */ submitting?: boolean; /** * Shows the development-only shortcut button at the top right of the * card: it fills the form with the host's `values`, and submits it * when asked to. Pass it only when the server says this is a * development environment: the kit never decides that itself, holds * no test data, and what the shortcut submits goes through the normal * path, so the server's own rules still decide. With neither `values` * nor `onClick` there is nothing to do and no button. */ devBypass?: RegistrationFormDevBypass; /** For React hosts: called with the values once every check has * passed. Not called when `fieldNames` is set. */ onSubmit?: (values: RegistrationFormValues) => void; /** * For a native form post: the host's own field names, e.g. * `{ email: 'registration[email]' }`. When set, the inputs carry * these names and the browser posts the form. A field without a name * here is not posted: name a confirm field only if the server's form * has one, or it may refuse the post as carrying extra fields. */ fieldNames?: RegistrationFormFieldNames; /** * Where a native form post goes. Default: the current address, query * string included, which is what a page reached through an invite link * needs. Only an address on this site is accepted: another site is * never sent what the user typed, and the post then goes to the * current address instead. */ action?: string; /** * Extra hidden inputs posted with a native form, by name: a CSRF token * or similar. Not used with `onSubmit`. A name that is also one of * `fieldNames` is left out: the form's own field wins. */ hiddenFields?: Readonly>; /** * Proves an email or a phone number with a code before the form * submits. For each field named here the card shows "Send code" beside * the field, a code box once a code is out, and locks the field * (read-only, still posted) when the code is right. The host sends and * checks the codes on its server, which must also refuse the form when * the value was not verified: this is a convenience for the person, * not the check. Without it the form is unchanged. * * `Confirm email` stays; leave `emailConfirm` out of `fields` to drop it. */ verification?: Partial>; /** * With `verification`, the form does not submit until every field named * there is verified. Default true. */ requireVerification?: boolean; } /** * The registration form card, for doctors and for patients. The host * picks the fields, supplies the page around the card and owns every * server rule; see the props for the two ways to submit. The card's * text follows the kit's language, like every kit component. */ export declare const RegistrationForm: import("react").ForwardRefExoticComponent>; //# sourceMappingURL=registration-form.d.ts.map