@alfadocs/ui-kit-debug 1.112.2 → 1.113.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/_chunks/{calendar-appointment-editor-dialog-FvdoKZ54.js → calendar-appointment-editor-dialog-CaZm5wGR.js} +2 -2
  2. package/dist/_chunks/{calendar-appointment-editor-dialog-FvdoKZ54.js.map → calendar-appointment-editor-dialog-CaZm5wGR.js.map} +1 -1
  3. package/dist/_chunks/email-input-DxwbREpx.js +156 -0
  4. package/dist/_chunks/email-input-DxwbREpx.js.map +1 -0
  5. package/dist/_chunks/{forgot-password-form-vfCO2-Tt.js → forgot-password-form-YQVzSskq.js} +8 -7
  6. package/dist/_chunks/{forgot-password-form-vfCO2-Tt.js.map → forgot-password-form-YQVzSskq.js.map} +1 -1
  7. package/dist/_chunks/isEmail-BfVspSvV.js +248 -0
  8. package/dist/_chunks/isEmail-BfVspSvV.js.map +1 -0
  9. package/dist/_chunks/{login-dev-card-Cz1Clugq.js → login-dev-card-B6-zCFq3.js} +47 -46
  10. package/dist/_chunks/{login-dev-card-Cz1Clugq.js.map → login-dev-card-B6-zCFq3.js.map} +1 -1
  11. package/dist/_chunks/{patient-details-BwkDIm4D.js → patient-details-RsT3SaYh.js} +2 -2
  12. package/dist/_chunks/{patient-details-BwkDIm4D.js.map → patient-details-RsT3SaYh.js.map} +1 -1
  13. package/dist/_chunks/{patient-field-row-CBba7w9V.js → patient-field-row-D9rb-QJH.js} +2 -2
  14. package/dist/_chunks/{patient-field-row-CBba7w9V.js.map → patient-field-row-D9rb-QJH.js.map} +1 -1
  15. package/dist/_chunks/{patient-summary-card-DtYTo9w_.js → patient-summary-card-BjZErlbt.js} +2 -2
  16. package/dist/_chunks/{patient-summary-card-DtYTo9w_.js.map → patient-summary-card-BjZErlbt.js.map} +1 -1
  17. package/dist/_chunks/{practice-results-BOpaPaav.js → practice-results-BByRCIuR.js} +620 -566
  18. package/dist/_chunks/practice-results-BByRCIuR.js.map +1 -0
  19. package/dist/_chunks/{registration-form-DEyUFysm.js → registration-form-Cq5_OSIL.js} +7 -6
  20. package/dist/_chunks/{registration-form-DEyUFysm.js.map → registration-form-Cq5_OSIL.js.map} +1 -1
  21. package/dist/_chunks/{reserved.agent-W_Zgj564.js → reserved.agent-BMkapgom.js} +2 -2
  22. package/dist/_chunks/{reserved.agent-W_Zgj564.js.map → reserved.agent-BMkapgom.js.map} +1 -1
  23. package/dist/_chunks/{reset-password-form-B0acanDD.js → reset-password-form-BVsL2fOJ.js} +2 -2
  24. package/dist/_chunks/{reset-password-form-B0acanDD.js.map → reset-password-form-BVsL2fOJ.js.map} +1 -1
  25. package/dist/_chunks/{send-registration-link-form-Nn0jf65G.js → send-registration-link-form-OgPomrZN.js} +8 -7
  26. package/dist/_chunks/{send-registration-link-form-Nn0jf65G.js.map → send-registration-link-form-OgPomrZN.js.map} +1 -1
  27. package/dist/_chunks/{use-appointment-details-read-DYyCYI9f.js → use-appointment-details-read-DvK7Looa.js} +2 -2
  28. package/dist/_chunks/{use-appointment-details-read-DYyCYI9f.js.map → use-appointment-details-read-DvK7Looa.js.map} +1 -1
  29. package/dist/_chunks/verify-identity-types-C85EXNzy.js +707 -0
  30. package/dist/_chunks/verify-identity-types-C85EXNzy.js.map +1 -0
  31. package/dist/agent-catalog.json +106 -2
  32. package/dist/agent-i18n/en.json +11 -0
  33. package/dist/components/appointment-details-panel/index.js +1 -1
  34. package/dist/components/booking/index.js +1 -1
  35. package/dist/components/email-input/index.js +1 -1
  36. package/dist/components/index.d.ts +1 -0
  37. package/dist/components/index.d.ts.map +1 -1
  38. package/dist/components/patient-details/index.js +1 -1
  39. package/dist/components/patient-summary-card/index.js +1 -1
  40. package/dist/components/practice-results/index.js +1 -1
  41. package/dist/components/practice-results/practice-results.d.ts +28 -0
  42. package/dist/components/practice-results/practice-results.d.ts.map +1 -1
  43. package/dist/core.css +1 -1
  44. package/dist/i18n/locales/ar.d.ts +67 -0
  45. package/dist/i18n/locales/ar.d.ts.map +1 -1
  46. package/dist/i18n/locales/ar.js +68 -1
  47. package/dist/i18n/locales/ar.js.map +1 -1
  48. package/dist/i18n/locales/de.d.ts +67 -0
  49. package/dist/i18n/locales/de.d.ts.map +1 -1
  50. package/dist/i18n/locales/de.js +68 -1
  51. package/dist/i18n/locales/de.js.map +1 -1
  52. package/dist/i18n/locales/el.d.ts +67 -0
  53. package/dist/i18n/locales/el.d.ts.map +1 -1
  54. package/dist/i18n/locales/el.js +68 -1
  55. package/dist/i18n/locales/el.js.map +1 -1
  56. package/dist/i18n/locales/en.d.ts +67 -0
  57. package/dist/i18n/locales/en.d.ts.map +1 -1
  58. package/dist/i18n/locales/en.js +67 -0
  59. package/dist/i18n/locales/en.js.map +1 -1
  60. package/dist/i18n/locales/es.d.ts +67 -0
  61. package/dist/i18n/locales/es.d.ts.map +1 -1
  62. package/dist/i18n/locales/es.js +68 -1
  63. package/dist/i18n/locales/es.js.map +1 -1
  64. package/dist/i18n/locales/fr.d.ts +67 -0
  65. package/dist/i18n/locales/fr.d.ts.map +1 -1
  66. package/dist/i18n/locales/fr.js +68 -1
  67. package/dist/i18n/locales/fr.js.map +1 -1
  68. package/dist/i18n/locales/hi.d.ts +67 -0
  69. package/dist/i18n/locales/hi.d.ts.map +1 -1
  70. package/dist/i18n/locales/hi.js +68 -1
  71. package/dist/i18n/locales/hi.js.map +1 -1
  72. package/dist/i18n/locales/it.d.ts +67 -0
  73. package/dist/i18n/locales/it.d.ts.map +1 -1
  74. package/dist/i18n/locales/it.js +68 -1
  75. package/dist/i18n/locales/it.js.map +1 -1
  76. package/dist/i18n/locales/ja.d.ts +67 -0
  77. package/dist/i18n/locales/ja.d.ts.map +1 -1
  78. package/dist/i18n/locales/ja.js +68 -1
  79. package/dist/i18n/locales/ja.js.map +1 -1
  80. package/dist/i18n/locales/nl.d.ts +67 -0
  81. package/dist/i18n/locales/nl.d.ts.map +1 -1
  82. package/dist/i18n/locales/nl.js +68 -1
  83. package/dist/i18n/locales/nl.js.map +1 -1
  84. package/dist/i18n/locales/pl.d.ts +67 -0
  85. package/dist/i18n/locales/pl.d.ts.map +1 -1
  86. package/dist/i18n/locales/pl.js +68 -1
  87. package/dist/i18n/locales/pl.js.map +1 -1
  88. package/dist/i18n/locales/pt.d.ts +67 -0
  89. package/dist/i18n/locales/pt.d.ts.map +1 -1
  90. package/dist/i18n/locales/pt.js +68 -1
  91. package/dist/i18n/locales/pt.js.map +1 -1
  92. package/dist/i18n/locales/ro.d.ts +67 -0
  93. package/dist/i18n/locales/ro.d.ts.map +1 -1
  94. package/dist/i18n/locales/ro.js +68 -1
  95. package/dist/i18n/locales/ro.js.map +1 -1
  96. package/dist/i18n/locales/ru.d.ts +67 -0
  97. package/dist/i18n/locales/ru.d.ts.map +1 -1
  98. package/dist/i18n/locales/ru.js +68 -1
  99. package/dist/i18n/locales/ru.js.map +1 -1
  100. package/dist/i18n/locales/sq.d.ts +67 -0
  101. package/dist/i18n/locales/sq.d.ts.map +1 -1
  102. package/dist/i18n/locales/sq.js +68 -1
  103. package/dist/i18n/locales/sq.js.map +1 -1
  104. package/dist/i18n/locales/sv.d.ts +67 -0
  105. package/dist/i18n/locales/sv.d.ts.map +1 -1
  106. package/dist/i18n/locales/sv.js +68 -1
  107. package/dist/i18n/locales/sv.js.map +1 -1
  108. package/dist/i18n/locales/tr.d.ts +67 -0
  109. package/dist/i18n/locales/tr.d.ts.map +1 -1
  110. package/dist/i18n/locales/tr.js +68 -1
  111. package/dist/i18n/locales/tr.js.map +1 -1
  112. package/dist/i18n/locales/zh.d.ts +67 -0
  113. package/dist/i18n/locales/zh.d.ts.map +1 -1
  114. package/dist/i18n/locales/zh.js +68 -1
  115. package/dist/i18n/locales/zh.js.map +1 -1
  116. package/dist/index.js +345 -340
  117. package/dist/index.js.map +1 -1
  118. package/dist/locales/ar.json +68 -1
  119. package/dist/locales/de.json +68 -1
  120. package/dist/locales/el.json +68 -1
  121. package/dist/locales/en.json +67 -0
  122. package/dist/locales/es.json +68 -1
  123. package/dist/locales/fr.json +68 -1
  124. package/dist/locales/hi.json +68 -1
  125. package/dist/locales/it.json +68 -1
  126. package/dist/locales/ja.json +68 -1
  127. package/dist/locales/nl.json +68 -1
  128. package/dist/locales/pl.json +68 -1
  129. package/dist/locales/pt.json +68 -1
  130. package/dist/locales/ro.json +68 -1
  131. package/dist/locales/ru.json +68 -1
  132. package/dist/locales/sq.json +68 -1
  133. package/dist/locales/sv.json +68 -1
  134. package/dist/locales/tr.json +68 -1
  135. package/dist/locales/zh.json +68 -1
  136. package/dist/patterns/calendar/index.js +1 -1
  137. package/dist/patterns/forgot-password-form/index.js +1 -1
  138. package/dist/patterns/login-form/index.js +1 -1
  139. package/dist/patterns/registration-form/index.js +1 -1
  140. package/dist/patterns/reset-password-form/index.js +1 -1
  141. package/dist/patterns/send-registration-link-form/index.js +1 -1
  142. package/dist/patterns/verify-identity/change-email-dialog.d.ts +26 -0
  143. package/dist/patterns/verify-identity/change-email-dialog.d.ts.map +1 -0
  144. package/dist/patterns/verify-identity/index.d.ts +7 -0
  145. package/dist/patterns/verify-identity/index.d.ts.map +1 -0
  146. package/dist/patterns/verify-identity/index.js +8 -0
  147. package/dist/patterns/verify-identity/index.js.map +1 -0
  148. package/dist/patterns/verify-identity/use-countdown.d.ts +12 -0
  149. package/dist/patterns/verify-identity/use-countdown.d.ts.map +1 -0
  150. package/dist/patterns/verify-identity/verify-identity-steps.d.ts +21 -0
  151. package/dist/patterns/verify-identity/verify-identity-steps.d.ts.map +1 -0
  152. package/dist/patterns/verify-identity/verify-identity-types.d.ts +47 -0
  153. package/dist/patterns/verify-identity/verify-identity-types.d.ts.map +1 -0
  154. package/dist/patterns/verify-identity/verify-identity.d.ts +54 -0
  155. package/dist/patterns/verify-identity/verify-identity.d.ts.map +1 -0
  156. package/dist/tokens.css +1 -1
  157. package/package.json +5 -1
  158. package/dist/_chunks/email-input-BEO3vonE.js +0 -399
  159. package/dist/_chunks/email-input-BEO3vonE.js.map +0 -1
  160. package/dist/_chunks/practice-results-BOpaPaav.js.map +0 -1
@@ -5,7 +5,7 @@ import { c as ws } from "./index-D2ZczOXr.js";
5
5
  import { A as u } from "./alert-C4WKViaS.js";
6
6
  import { B as D } from "./button-DohK_Ak_.js";
7
7
  import { C as ms } from "./card-C85_Ndhb.js";
8
- import { E as ks } from "./email-input-BEO3vonE.js";
8
+ import { E as ks } from "./email-input-DxwbREpx.js";
9
9
  import { E as Vs } from "./error-summary-DxNhwf_G.js";
10
10
  import { F as L } from "./form-field-CyHfOVKF.js";
11
11
  import { P as us } from "./password-input-SJGHFdOO.js";
@@ -364,4 +364,4 @@ export {
364
364
  b as R,
365
365
  nr as a
366
366
  };
367
- //# sourceMappingURL=reset-password-form-B0acanDD.js.map
367
+ //# sourceMappingURL=reset-password-form-BVsL2fOJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reset-password-form-B0acanDD.js","sources":["../../src/patterns/_shared/password-policy.ts","../../src/patterns/reset-password-form/reset-password-form.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* The platform's password rule, as the live checklist shows it. */\n/* */\n/* The platform's rule is written in ASCII (`[A-Z]`, `[a-z]`, `\\d`), so */\n/* the checklist counts the same characters and never shows green for a */\n/* password the server will refuse. Shipped with the patterns that */\n/* import it; not an export of its own. */\n/* -------------------------------------------------------------------- */\n\nimport type { UsePasswordRequirementsOptions } from '../../components/password-input';\n\nexport const PLATFORM_PASSWORD_POLICY: UsePasswordRequirementsOptions = {\n minLength: 12,\n uppercase: true,\n lowercase: true,\n digit: true,\n charset: 'ascii',\n};\n","/* -------------------------------------------------------------------- */\n/* ResetPasswordForm — the card the reset email opens, where the person */\n/* chooses a new password. */\n/* */\n/* Two password fields with the live rules checklist, then one of two */\n/* results in place of the form: the password has changed, or the link */\n/* has expired. The host checks the link and the code, sets the state */\n/* and owns every server rule; the card checks what a browser can check, */\n/* then hands the values to `onSubmit` or posts a real form. A password */\n/* is never put in an attribute. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { EmailInput } from '../../components/email-input';\nimport { ErrorSummary } from '../../components/error-summary';\nimport { FormField } from '../../components/form-field';\nimport {\n PasswordInput,\n usePasswordRequirements,\n} from '../../components/password-input';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport { useStateBackedInput } from '../../components/_shared/use-state-backed-input';\nimport { useFieldMatch } from '../../hooks/use-field-match';\nimport {\n AuthCardHeading,\n AuthFormMessage,\n AuthFormStatus,\n ExtraFields,\n useExtraFields,\n useFormAction,\n} from '../_shared/auth-form-parts';\nimport type { BrandMarkMotion } from '../_shared/brand-mark';\nimport { PLATFORM_PASSWORD_POLICY } from '../_shared/password-policy';\nimport {\n useErrorSummary,\n useFormMessageAnnounce,\n} from '../_shared/use-error-summary';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The form's two fields. */\nexport const RESET_PASSWORD_FORM_FIELDS = [\n 'password',\n 'passwordConfirm',\n] as const;\n\nexport type ResetPasswordFormField =\n (typeof RESET_PASSWORD_FORM_FIELDS)[number];\n\n/** What the card shows: the form, the result after a good change, or the\n * result for a link that no longer works. */\nexport type ResetPasswordFormState = 'form' | 'done' | 'expired';\n\n/** What `onSubmit` receives once both passwords have passed their checks. */\nexport interface ResetPasswordFormValues {\n password: string;\n passwordConfirm: string;\n}\n\n/** Messages from the server, already translated: one for each field, plus\n * `form` for a message about the whole form. */\nexport type ResetPasswordFormErrors = Partial<\n Record<ResetPasswordFormField | 'form', string>\n>;\n\n/** The host's own form field names, for a native form post. They are\n * needed: a field without a name is not posted. */\nexport type ResetPasswordFormFieldNames = Record<\n ResetPasswordFormField,\n string\n>;\n\nexport interface ResetPasswordFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /**\n * What the card shows. Default `form`. `done` and `expired` replace the\n * form and take focus when they appear.\n */\n state?: ResetPasswordFormState;\n /** Replaces the form's heading \"Choose a new password\". Pass it\n * translated. The result states have their own heading. */\n title?: string;\n /** Replaces the line under the form's heading (\"Enter a new password\n * for your account.\"). Pass it translated. */\n description?: string;\n /**\n * The heading's level. Default 1: this page usually has no other\n * heading. Pass 2 on a page that has its own `h1`.\n */\n headingLevel?: 1 | 2 | 3;\n /** Shows the Alfadocs mark above the heading. Default true. */\n showLogo?: boolean;\n /** How the mark arrives when the card opens. Default `assemble`. */\n logoMotion?: BrandMarkMotion;\n /**\n * Host content between the heading and the fields, such as a notice. It\n * sits outside the form, so nothing in it is posted.\n */\n children?: ReactNode;\n /**\n * The address the password is for. In the form it shows read-only, and\n * is the username a password manager saves the new password under. In\n * the `done` state it is named in the line under the result.\n */\n email?: string;\n /**\n * The `done` state's action, \"Sign in\". A path on the same site, or an\n * address written in full. Anything else shows no button.\n */\n loginHref?: string;\n /**\n * The `expired` state's action, \"Ask for a new link\". A path on the\n * same site, or an address written in full. Anything else shows no\n * button.\n */\n requestHref?: string;\n /**\n * Messages from the server, already translated. A field's message shows\n * on the field until the user changes it; `form` shows above the\n * fields. When messages arrive, focus moves to the error summary when a\n * field has one, or to the message above the fields when only that\n * says something. Passwords the server refused are emptied.\n */\n errors?: ResetPasswordFormErrors;\n /** Replaces the button's \"Change password\". Pass it translated. */\n submitLabel?: string;\n /**\n * True while the host sends the passwords: the button shows a spinner\n * and a second submit is ignored. Set it inside `onSubmit`, before\n * anything is awaited.\n */\n submitting?: boolean;\n /** For React hosts: called with both passwords once they have passed\n * their checks. Not called when `fieldNames` is set. */\n onSubmit?: (values: ResetPasswordFormValues) => void;\n /**\n * For a native form post: the host's own field names, e.g.\n * `{ password: 'lost_password_reset[password1]', passwordConfirm:\n * 'lost_password_reset[password2]' }`. When set, the inputs carry those\n * names and the browser posts the form.\n */\n fieldNames?: ResetPasswordFormFieldNames;\n /**\n * Where a native form post goes. Default: the current address. Only a\n * path, or an address on the page's own origin, is accepted: another\n * origin is never sent what the user typed. Does nothing without\n * `fieldNames`.\n */\n action?: string;\n /**\n * Extra hidden inputs posted with a native form, by name: a CSRF token,\n * e.g. `{ 'lost_password_reset[_token]': token }`. Not used with\n * `onSubmit`. A name that is also in `fieldNames` is left out.\n */\n hiddenFields?: Readonly<Record<string, string>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Styles */\n/* -------------------------------------------------------------------- */\n\n// 400px at most, in px: a host whose root font size is not 16px would\n// stretch or squeeze a width in rem.\nconst resetPasswordFormVariants = cva(\n 'ds:mx-auto ds:w-full ds:max-w-[400px] ds:text-start ds:text-[var(--foreground)]',\n);\n\n// The result takes focus when it appears, so it shows a ring.\nconst resultVariants = cva(\n 'ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]',\n);\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\ntype FocusTarget = ResetPasswordFormField | 'form';\n\n/** Unicode isolates: they keep an address's order inside any sentence. */\nconst LTR_ISOLATE = '\\u2066';\nconst POP_ISOLATE = '\\u2069';\n\n/** The result's heading, by the level of the card's own. */\nconst RESULT_HEADING = { 1: 'h2', 2: 'h3', 3: 'h4' } as const;\n\nconst hasMessage = (errors: ResetPasswordFormErrors): boolean =>\n Object.values(errors).some(Boolean);\n\nconst focusTargetFor = (\n messages: ResetPasswordFormErrors,\n): FocusTarget | undefined =>\n RESET_PASSWORD_FORM_FIELDS.find((field) => messages[field]) ??\n (messages.form ? 'form' : undefined);\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\n/**\n * The card for the page the reset email opens. Mount it on the\n * reset-password page, inside `SignedOutFrame` or the host's own chrome.\n */\nexport const ResetPasswordForm = forwardRef<\n HTMLDivElement,\n ResetPasswordFormProps\n>(\n (\n {\n state = 'form',\n title,\n description,\n headingLevel = 1,\n showLogo = true,\n logoMotion = 'assemble',\n children,\n email,\n loginHref,\n requestHref,\n errors,\n submitLabel,\n submitting = false,\n onSubmit,\n fieldNames,\n action,\n hiddenFields,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const titleId = useId();\n const resultTitleId = useId();\n const resultDescriptionId = useId();\n const emailFieldId = useId();\n const passwordFieldId = useId();\n const passwordConfirmFieldId = useId();\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n const fieldIds: Record<ResetPasswordFormField, string> = {\n password: passwordFieldId,\n passwordConfirm: passwordConfirmFieldId,\n };\n\n /* ------------------------------ State ----------------------------- */\n\n // Passwords always start empty and are held in state only: the inputs\n // get them as a DOM property, never as an attribute.\n const [values, setValues] = useState<ResetPasswordFormValues>({\n password: '',\n passwordConfirm: '',\n });\n const [touched, setTouched] = useState<\n Partial<Record<ResetPasswordFormField, boolean>>\n >({});\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] = useState<ResetPasswordFormErrors>(\n () => errors ?? {},\n );\n\n const set = (field: ResetPasswordFormField, value: string) => {\n setValues((previous) => ({ ...previous, [field]: value }));\n // The server's message was about the old value.\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n };\n const leave = (field: ResetPasswordFormField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n const emptyPasswords = () => {\n setValues({ password: '', passwordConfirm: '' });\n setTouched({});\n };\n\n /* ---------------------------- Validation -------------------------- */\n\n const requirements = usePasswordRequirements(PLATFORM_PASSWORD_POLICY);\n const match = useFieldMatch({\n value: values.password,\n confirmValue: values.passwordConfirm,\n kind: 'password',\n submitted,\n });\n\n /** What stops a submit, whether or not the message shows yet. */\n const invalid: Record<ResetPasswordFormField, boolean> = {\n password:\n values.password === '' ||\n !requirements.every((rule) => rule.test(values.password)),\n passwordConfirm: values.passwordConfirm === '' || !match.matches,\n };\n // A message shows once the user has left the field or tried to submit.\n const due = (field: ResetPasswordFormField) =>\n submitted || touched[field] === true;\n const ownErrors: Record<ResetPasswordFormField, string | undefined> = {\n password:\n due('password') && invalid.password\n ? values.password === ''\n ? t('resetPasswordForm.passwordRequired')\n : t('resetPasswordForm.passwordInvalid')\n : undefined,\n passwordConfirm:\n values.passwordConfirm === ''\n ? due('passwordConfirm')\n ? t('resetPasswordForm.passwordConfirmRequired')\n : undefined\n : match.error,\n };\n const errorFor = (field: ResetPasswordFormField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n const controls = useRef<\n Partial<Record<ResetPasswordFormField, HTMLElement | null>>\n >({});\n const control = useMemo(\n () => ({\n password: (node: HTMLElement | null) => {\n controls.current.password = node;\n },\n passwordConfirm: (node: HTMLElement | null) => {\n controls.current.passwordConfirm = node;\n },\n }),\n [],\n );\n const formMessage = useRef<HTMLDivElement>(null);\n const result = useRef<HTMLDivElement>(null);\n\n // The address stays out of the input's `value` attribute, where a\n // copied outerHTML or a session replay could read it.\n const emailInput = useRef<HTMLInputElement>(null);\n const emailField = useStateBackedInput(email ?? '', emailInput);\n\n // Every field with a message after a refused submit, or after a server\n // answer, is listed at the top of the form, and focus goes there. A\n // page the server rendered after a failed post opens that way too.\n const [openedWithFieldMessage] = useState(() =>\n RESET_PASSWORD_FORM_FIELDS.some((field) => Boolean(errors?.[field])),\n );\n const summary = useErrorSummary(\n RESET_PASSWORD_FORM_FIELDS,\n errorFor,\n openedWithFieldMessage,\n );\n const formMessageAnnounce = useFormMessageAnnounce(\n serverErrors.form,\n summary.listed.length > 0,\n );\n\n // A new object for each request, so asking twice for the same place\n // moves focus twice.\n const [focusRequest, setFocusRequest] = useState<{\n target: FocusTarget;\n } | null>(() => {\n const target = openedWithFieldMessage\n ? undefined\n : focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (!focusRequest) return;\n if (focusRequest.target === 'form') formMessage.current?.focus();\n else controls.current[focusRequest.target]?.focus();\n }, [focusRequest]);\n\n // The form, and the button that had focus, are gone once a result\n // shows. Move focus to it. Not on a page that opens on a result: that\n // one is read from the top like any other.\n // A password does not wait in memory behind a result.\n const clearOnResult = state !== 'form';\n useEffect(() => {\n if (clearOnResult) {\n setValues({ password: '', passwordConfirm: '' });\n setTouched({});\n }\n }, [clearOnResult]);\n const wasForm = useRef(state === 'form');\n useEffect(() => {\n if (state !== 'form' && wasForm.current) result.current?.focus();\n wasForm.current = state === 'form';\n }, [state]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<ResetPasswordFormField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () =>\n RESET_PASSWORD_FORM_FIELDS.find((field) => invalid[field]),\n onRefused: (field) => {\n setSubmitted(true);\n summary.open(() => setFocusRequest({ target: field }));\n },\n // Only a React host gets here: a native post is the browser's own.\n deliver: () =>\n onSubmit?.({\n password: values.password,\n passwordConfirm: values.passwordConfirm,\n }),\n onAnswer: (answer) => {\n const next: ResetPasswordFormErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n // Never keep a password the server did not accept.\n emptyPasswords();\n setSubmitted(false);\n summary.open(() => {\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n });\n },\n // The page came back from the browser's cache as it was left: the\n // passwords must not come back with it.\n onRestore: emptyPasswords,\n });\n const { busy } = submit;\n\n /* ------------------------------ Render ---------------------------- */\n\n const formAction = useFormAction('ResetPasswordForm', native, action);\n const extraFields = useExtraFields(\n 'ResetPasswordForm',\n native,\n fieldNames,\n hiddenFields,\n );\n const name = (field: ResetPasswordFormField) =>\n native ? fieldNames[field] : field;\n const safe = (href: string | undefined) =>\n href && isSafeHref(href) ? href : undefined;\n const loginLink = safe(loginHref);\n const requestLink = safe(requestHref);\n const showingForm = state === 'form';\n const labels: Record<ResetPasswordFormField, string> = {\n password: t('resetPasswordForm.password'),\n passwordConfirm: t('resetPasswordForm.passwordConfirm'),\n };\n const resultHeading = RESULT_HEADING[headingLevel];\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"reset-password-form\"\n data-state={state}\n className={resetPasswordFormVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <AuthCardHeading\n id={titleId}\n title={\n showingForm\n ? (title ?? t('resetPasswordForm.title'))\n : t('resetPasswordForm.pageTitle')\n }\n description={\n showingForm\n ? (description ?? t('resetPasswordForm.description'))\n : undefined\n }\n level={headingLevel}\n showLogo={showLogo}\n logoMotion={logoMotion}\n />\n\n {children ? (\n <div\n data-slot=\"host-content\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {children}\n </div>\n ) : null}\n\n {state === 'done' && (\n <>\n <Alert\n ref={result}\n variant=\"success\"\n tabIndex={-1}\n aria-labelledby={resultTitleId}\n aria-describedby={resultDescriptionId}\n data-slot=\"result\"\n className={resultVariants()}\n >\n <Alert.Title id={resultTitleId} as={resultHeading}>\n {t('resetPasswordForm.doneTitle')}\n </Alert.Title>\n <Alert.Description id={resultDescriptionId}>\n {email\n ? t('resetPasswordForm.doneDescriptionEmail', {\n // Isolated left to right, so the address keeps its\n // order inside a right-to-left sentence.\n email: `${LTR_ISOLATE}${email}${POP_ISOLATE}`,\n })\n : t('resetPasswordForm.doneDescription')}\n </Alert.Description>\n </Alert>\n {loginLink && (\n <Button\n asChild\n intent=\"primary\"\n size=\"lg\"\n className=\"ds:w-full\"\n >\n <a href={loginLink} data-action=\"login\">\n {t('resetPasswordForm.signIn')}\n </a>\n </Button>\n )}\n </>\n )}\n\n {state === 'expired' && (\n <>\n <Alert\n ref={result}\n variant=\"warning\"\n // Focus moves here: an assertive alert as well would read\n // it twice, and over a page that opens on it.\n announce=\"polite\"\n tabIndex={-1}\n aria-labelledby={resultTitleId}\n aria-describedby={resultDescriptionId}\n data-slot=\"result\"\n className={resultVariants()}\n >\n <Alert.Title id={resultTitleId} as={resultHeading}>\n {t('resetPasswordForm.expiredTitle')}\n </Alert.Title>\n <Alert.Description id={resultDescriptionId}>\n {t('resetPasswordForm.expiredDescription')}\n </Alert.Description>\n </Alert>\n {requestLink && (\n <Button\n asChild\n intent=\"primary\"\n size=\"lg\"\n className=\"ds:w-full\"\n >\n <a href={requestLink} data-action=\"request-link\">\n {t('resetPasswordForm.requestLink')}\n </a>\n </Button>\n )}\n </>\n )}\n\n {showingForm && (\n <>\n <form\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <ErrorSummary\n ref={summary.ref}\n headingLevel={(headingLevel + 1) as 2 | 3 | 4}\n // The message about the whole form is read with it.\n aria-describedby={\n serverErrors.form ? formMessageId : undefined\n }\n errors={summary.listed.map((field) => ({\n field,\n message: errorFor(field) ?? '',\n targetId: fieldIds[field],\n }))}\n />\n\n {serverErrors.form && (\n <AuthFormMessage\n ref={formMessage}\n id={formMessageId}\n announce={formMessageAnnounce}\n >\n {serverErrors.form}\n </AuthFormMessage>\n )}\n\n {email ? (\n <FormField\n id={emailFieldId}\n label={t('resetPasswordForm.email')}\n data-field=\"email\"\n >\n {/* Read-only, and not posted: it has no name. `username`\n is what password managers pair with\n `new-password`, so the new password is saved under\n this address. */}\n <EmailInput\n ref={emailField.ref}\n name=\"\"\n readOnly\n autoComplete=\"username\"\n // An address reads left to right in any language.\n dir=\"ltr\"\n disableBuiltInValidation\n onChange={emailField.quiet()}\n />\n </FormField>\n ) : null}\n\n <FormField\n id={passwordFieldId}\n label={labels.password}\n required\n error={errorFor('password')}\n announceError={!summary.lists('password')}\n data-field=\"password\"\n >\n {/* PasswordInput names itself \"password\" when given no\n name; an empty one keeps a field out of the post. */}\n <PasswordInput\n ref={control.password}\n name={name('password')}\n autoComplete=\"new-password\"\n requirements={requirements}\n value={values.password}\n onChange={(event) => set('password', event.target.value)}\n onBlur={() => leave('password')}\n />\n </FormField>\n\n <FormField\n id={passwordConfirmFieldId}\n label={labels.passwordConfirm}\n required\n error={errorFor('passwordConfirm')}\n announceError={!summary.lists('passwordConfirm')}\n data-field=\"passwordConfirm\"\n >\n <PasswordInput\n ref={control.passwordConfirm}\n name={name('passwordConfirm')}\n autoComplete=\"new-password\"\n value={values.passwordConfirm}\n onChange={(event) =>\n set('passwordConfirm', event.target.value)\n }\n onBlur={() => {\n leave('passwordConfirm');\n match.confirmProps.onBlur();\n }}\n />\n </FormField>\n\n <ExtraFields fields={extraFields} />\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('resetPasswordForm.submit')}\n </Button>\n </form>\n {/* Outside the form: a screen reader may hold back what\n changes inside a busy region. */}\n <AuthFormStatus busy={busy} />\n </>\n )}\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nResetPasswordForm.displayName = 'ResetPasswordForm';\n"],"names":["PLATFORM_PASSWORD_POLICY","RESET_PASSWORD_FORM_FIELDS","resetPasswordFormVariants","cva","resultVariants","LTR_ISOLATE","POP_ISOLATE","RESULT_HEADING","hasMessage","errors","focusTargetFor","messages","field","ResetPasswordForm","forwardRef","state","title","description","headingLevel","showLogo","logoMotion","children","email","loginHref","requestHref","submitLabel","submitting","onSubmit","fieldNames","action","hiddenFields","className","rest","ref","t","useTranslation","titleId","useId","resultTitleId","resultDescriptionId","emailFieldId","passwordFieldId","passwordConfirmFieldId","formMessageId","native","fieldIds","values","setValues","useState","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","set","value","previous","leave","emptyPasswords","requirements","usePasswordRequirements","match","useFieldMatch","invalid","rule","due","ownErrors","errorFor","controls","useRef","control","useMemo","node","formMessage","result","emailInput","emailField","useStateBackedInput","openedWithFieldMessage","summary","useErrorSummary","formMessageAnnounce","useFormMessageAnnounce","focusRequest","setFocusRequest","target","useEffect","_a","_b","clearOnResult","wasForm","submit","useRegistrationSubmit","answer","next","busy","formAction","useFormAction","extraFields","useExtraFields","name","safe","href","isSafeHref","loginLink","requestLink","showingForm","labels","resultHeading","jsx","Card","AuthCardHeading","jsxs","Fragment","Alert","Button","ErrorSummary","AuthFormMessage","FormField","EmailInput","PasswordInput","event","ExtraFields","AuthFormStatus"],"mappings":"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"}
1
+ {"version":3,"file":"reset-password-form-BVsL2fOJ.js","sources":["../../src/patterns/_shared/password-policy.ts","../../src/patterns/reset-password-form/reset-password-form.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* The platform's password rule, as the live checklist shows it. */\n/* */\n/* The platform's rule is written in ASCII (`[A-Z]`, `[a-z]`, `\\d`), so */\n/* the checklist counts the same characters and never shows green for a */\n/* password the server will refuse. Shipped with the patterns that */\n/* import it; not an export of its own. */\n/* -------------------------------------------------------------------- */\n\nimport type { UsePasswordRequirementsOptions } from '../../components/password-input';\n\nexport const PLATFORM_PASSWORD_POLICY: UsePasswordRequirementsOptions = {\n minLength: 12,\n uppercase: true,\n lowercase: true,\n digit: true,\n charset: 'ascii',\n};\n","/* -------------------------------------------------------------------- */\n/* ResetPasswordForm — the card the reset email opens, where the person */\n/* chooses a new password. */\n/* */\n/* Two password fields with the live rules checklist, then one of two */\n/* results in place of the form: the password has changed, or the link */\n/* has expired. The host checks the link and the code, sets the state */\n/* and owns every server rule; the card checks what a browser can check, */\n/* then hands the values to `onSubmit` or posts a real form. A password */\n/* is never put in an attribute. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { EmailInput } from '../../components/email-input';\nimport { ErrorSummary } from '../../components/error-summary';\nimport { FormField } from '../../components/form-field';\nimport {\n PasswordInput,\n usePasswordRequirements,\n} from '../../components/password-input';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport { useStateBackedInput } from '../../components/_shared/use-state-backed-input';\nimport { useFieldMatch } from '../../hooks/use-field-match';\nimport {\n AuthCardHeading,\n AuthFormMessage,\n AuthFormStatus,\n ExtraFields,\n useExtraFields,\n useFormAction,\n} from '../_shared/auth-form-parts';\nimport type { BrandMarkMotion } from '../_shared/brand-mark';\nimport { PLATFORM_PASSWORD_POLICY } from '../_shared/password-policy';\nimport {\n useErrorSummary,\n useFormMessageAnnounce,\n} from '../_shared/use-error-summary';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The form's two fields. */\nexport const RESET_PASSWORD_FORM_FIELDS = [\n 'password',\n 'passwordConfirm',\n] as const;\n\nexport type ResetPasswordFormField =\n (typeof RESET_PASSWORD_FORM_FIELDS)[number];\n\n/** What the card shows: the form, the result after a good change, or the\n * result for a link that no longer works. */\nexport type ResetPasswordFormState = 'form' | 'done' | 'expired';\n\n/** What `onSubmit` receives once both passwords have passed their checks. */\nexport interface ResetPasswordFormValues {\n password: string;\n passwordConfirm: string;\n}\n\n/** Messages from the server, already translated: one for each field, plus\n * `form` for a message about the whole form. */\nexport type ResetPasswordFormErrors = Partial<\n Record<ResetPasswordFormField | 'form', string>\n>;\n\n/** The host's own form field names, for a native form post. They are\n * needed: a field without a name is not posted. */\nexport type ResetPasswordFormFieldNames = Record<\n ResetPasswordFormField,\n string\n>;\n\nexport interface ResetPasswordFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /**\n * What the card shows. Default `form`. `done` and `expired` replace the\n * form and take focus when they appear.\n */\n state?: ResetPasswordFormState;\n /** Replaces the form's heading \"Choose a new password\". Pass it\n * translated. The result states have their own heading. */\n title?: string;\n /** Replaces the line under the form's heading (\"Enter a new password\n * for your account.\"). Pass it translated. */\n description?: string;\n /**\n * The heading's level. Default 1: this page usually has no other\n * heading. Pass 2 on a page that has its own `h1`.\n */\n headingLevel?: 1 | 2 | 3;\n /** Shows the Alfadocs mark above the heading. Default true. */\n showLogo?: boolean;\n /** How the mark arrives when the card opens. Default `assemble`. */\n logoMotion?: BrandMarkMotion;\n /**\n * Host content between the heading and the fields, such as a notice. It\n * sits outside the form, so nothing in it is posted.\n */\n children?: ReactNode;\n /**\n * The address the password is for. In the form it shows read-only, and\n * is the username a password manager saves the new password under. In\n * the `done` state it is named in the line under the result.\n */\n email?: string;\n /**\n * The `done` state's action, \"Sign in\". A path on the same site, or an\n * address written in full. Anything else shows no button.\n */\n loginHref?: string;\n /**\n * The `expired` state's action, \"Ask for a new link\". A path on the\n * same site, or an address written in full. Anything else shows no\n * button.\n */\n requestHref?: string;\n /**\n * Messages from the server, already translated. A field's message shows\n * on the field until the user changes it; `form` shows above the\n * fields. When messages arrive, focus moves to the error summary when a\n * field has one, or to the message above the fields when only that\n * says something. Passwords the server refused are emptied.\n */\n errors?: ResetPasswordFormErrors;\n /** Replaces the button's \"Change password\". Pass it translated. */\n submitLabel?: string;\n /**\n * True while the host sends the passwords: the button shows a spinner\n * and a second submit is ignored. Set it inside `onSubmit`, before\n * anything is awaited.\n */\n submitting?: boolean;\n /** For React hosts: called with both passwords once they have passed\n * their checks. Not called when `fieldNames` is set. */\n onSubmit?: (values: ResetPasswordFormValues) => void;\n /**\n * For a native form post: the host's own field names, e.g.\n * `{ password: 'lost_password_reset[password1]', passwordConfirm:\n * 'lost_password_reset[password2]' }`. When set, the inputs carry those\n * names and the browser posts the form.\n */\n fieldNames?: ResetPasswordFormFieldNames;\n /**\n * Where a native form post goes. Default: the current address. Only a\n * path, or an address on the page's own origin, is accepted: another\n * origin is never sent what the user typed. Does nothing without\n * `fieldNames`.\n */\n action?: string;\n /**\n * Extra hidden inputs posted with a native form, by name: a CSRF token,\n * e.g. `{ 'lost_password_reset[_token]': token }`. Not used with\n * `onSubmit`. A name that is also in `fieldNames` is left out.\n */\n hiddenFields?: Readonly<Record<string, string>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Styles */\n/* -------------------------------------------------------------------- */\n\n// 400px at most, in px: a host whose root font size is not 16px would\n// stretch or squeeze a width in rem.\nconst resetPasswordFormVariants = cva(\n 'ds:mx-auto ds:w-full ds:max-w-[400px] ds:text-start ds:text-[var(--foreground)]',\n);\n\n// The result takes focus when it appears, so it shows a ring.\nconst resultVariants = cva(\n 'ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]',\n);\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\ntype FocusTarget = ResetPasswordFormField | 'form';\n\n/** Unicode isolates: they keep an address's order inside any sentence. */\nconst LTR_ISOLATE = '\\u2066';\nconst POP_ISOLATE = '\\u2069';\n\n/** The result's heading, by the level of the card's own. */\nconst RESULT_HEADING = { 1: 'h2', 2: 'h3', 3: 'h4' } as const;\n\nconst hasMessage = (errors: ResetPasswordFormErrors): boolean =>\n Object.values(errors).some(Boolean);\n\nconst focusTargetFor = (\n messages: ResetPasswordFormErrors,\n): FocusTarget | undefined =>\n RESET_PASSWORD_FORM_FIELDS.find((field) => messages[field]) ??\n (messages.form ? 'form' : undefined);\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\n/**\n * The card for the page the reset email opens. Mount it on the\n * reset-password page, inside `SignedOutFrame` or the host's own chrome.\n */\nexport const ResetPasswordForm = forwardRef<\n HTMLDivElement,\n ResetPasswordFormProps\n>(\n (\n {\n state = 'form',\n title,\n description,\n headingLevel = 1,\n showLogo = true,\n logoMotion = 'assemble',\n children,\n email,\n loginHref,\n requestHref,\n errors,\n submitLabel,\n submitting = false,\n onSubmit,\n fieldNames,\n action,\n hiddenFields,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const titleId = useId();\n const resultTitleId = useId();\n const resultDescriptionId = useId();\n const emailFieldId = useId();\n const passwordFieldId = useId();\n const passwordConfirmFieldId = useId();\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n const fieldIds: Record<ResetPasswordFormField, string> = {\n password: passwordFieldId,\n passwordConfirm: passwordConfirmFieldId,\n };\n\n /* ------------------------------ State ----------------------------- */\n\n // Passwords always start empty and are held in state only: the inputs\n // get them as a DOM property, never as an attribute.\n const [values, setValues] = useState<ResetPasswordFormValues>({\n password: '',\n passwordConfirm: '',\n });\n const [touched, setTouched] = useState<\n Partial<Record<ResetPasswordFormField, boolean>>\n >({});\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] = useState<ResetPasswordFormErrors>(\n () => errors ?? {},\n );\n\n const set = (field: ResetPasswordFormField, value: string) => {\n setValues((previous) => ({ ...previous, [field]: value }));\n // The server's message was about the old value.\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n };\n const leave = (field: ResetPasswordFormField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n const emptyPasswords = () => {\n setValues({ password: '', passwordConfirm: '' });\n setTouched({});\n };\n\n /* ---------------------------- Validation -------------------------- */\n\n const requirements = usePasswordRequirements(PLATFORM_PASSWORD_POLICY);\n const match = useFieldMatch({\n value: values.password,\n confirmValue: values.passwordConfirm,\n kind: 'password',\n submitted,\n });\n\n /** What stops a submit, whether or not the message shows yet. */\n const invalid: Record<ResetPasswordFormField, boolean> = {\n password:\n values.password === '' ||\n !requirements.every((rule) => rule.test(values.password)),\n passwordConfirm: values.passwordConfirm === '' || !match.matches,\n };\n // A message shows once the user has left the field or tried to submit.\n const due = (field: ResetPasswordFormField) =>\n submitted || touched[field] === true;\n const ownErrors: Record<ResetPasswordFormField, string | undefined> = {\n password:\n due('password') && invalid.password\n ? values.password === ''\n ? t('resetPasswordForm.passwordRequired')\n : t('resetPasswordForm.passwordInvalid')\n : undefined,\n passwordConfirm:\n values.passwordConfirm === ''\n ? due('passwordConfirm')\n ? t('resetPasswordForm.passwordConfirmRequired')\n : undefined\n : match.error,\n };\n const errorFor = (field: ResetPasswordFormField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n const controls = useRef<\n Partial<Record<ResetPasswordFormField, HTMLElement | null>>\n >({});\n const control = useMemo(\n () => ({\n password: (node: HTMLElement | null) => {\n controls.current.password = node;\n },\n passwordConfirm: (node: HTMLElement | null) => {\n controls.current.passwordConfirm = node;\n },\n }),\n [],\n );\n const formMessage = useRef<HTMLDivElement>(null);\n const result = useRef<HTMLDivElement>(null);\n\n // The address stays out of the input's `value` attribute, where a\n // copied outerHTML or a session replay could read it.\n const emailInput = useRef<HTMLInputElement>(null);\n const emailField = useStateBackedInput(email ?? '', emailInput);\n\n // Every field with a message after a refused submit, or after a server\n // answer, is listed at the top of the form, and focus goes there. A\n // page the server rendered after a failed post opens that way too.\n const [openedWithFieldMessage] = useState(() =>\n RESET_PASSWORD_FORM_FIELDS.some((field) => Boolean(errors?.[field])),\n );\n const summary = useErrorSummary(\n RESET_PASSWORD_FORM_FIELDS,\n errorFor,\n openedWithFieldMessage,\n );\n const formMessageAnnounce = useFormMessageAnnounce(\n serverErrors.form,\n summary.listed.length > 0,\n );\n\n // A new object for each request, so asking twice for the same place\n // moves focus twice.\n const [focusRequest, setFocusRequest] = useState<{\n target: FocusTarget;\n } | null>(() => {\n const target = openedWithFieldMessage\n ? undefined\n : focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (!focusRequest) return;\n if (focusRequest.target === 'form') formMessage.current?.focus();\n else controls.current[focusRequest.target]?.focus();\n }, [focusRequest]);\n\n // The form, and the button that had focus, are gone once a result\n // shows. Move focus to it. Not on a page that opens on a result: that\n // one is read from the top like any other.\n // A password does not wait in memory behind a result.\n const clearOnResult = state !== 'form';\n useEffect(() => {\n if (clearOnResult) {\n setValues({ password: '', passwordConfirm: '' });\n setTouched({});\n }\n }, [clearOnResult]);\n const wasForm = useRef(state === 'form');\n useEffect(() => {\n if (state !== 'form' && wasForm.current) result.current?.focus();\n wasForm.current = state === 'form';\n }, [state]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<ResetPasswordFormField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () =>\n RESET_PASSWORD_FORM_FIELDS.find((field) => invalid[field]),\n onRefused: (field) => {\n setSubmitted(true);\n summary.open(() => setFocusRequest({ target: field }));\n },\n // Only a React host gets here: a native post is the browser's own.\n deliver: () =>\n onSubmit?.({\n password: values.password,\n passwordConfirm: values.passwordConfirm,\n }),\n onAnswer: (answer) => {\n const next: ResetPasswordFormErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n // Never keep a password the server did not accept.\n emptyPasswords();\n setSubmitted(false);\n summary.open(() => {\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n });\n },\n // The page came back from the browser's cache as it was left: the\n // passwords must not come back with it.\n onRestore: emptyPasswords,\n });\n const { busy } = submit;\n\n /* ------------------------------ Render ---------------------------- */\n\n const formAction = useFormAction('ResetPasswordForm', native, action);\n const extraFields = useExtraFields(\n 'ResetPasswordForm',\n native,\n fieldNames,\n hiddenFields,\n );\n const name = (field: ResetPasswordFormField) =>\n native ? fieldNames[field] : field;\n const safe = (href: string | undefined) =>\n href && isSafeHref(href) ? href : undefined;\n const loginLink = safe(loginHref);\n const requestLink = safe(requestHref);\n const showingForm = state === 'form';\n const labels: Record<ResetPasswordFormField, string> = {\n password: t('resetPasswordForm.password'),\n passwordConfirm: t('resetPasswordForm.passwordConfirm'),\n };\n const resultHeading = RESULT_HEADING[headingLevel];\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"reset-password-form\"\n data-state={state}\n className={resetPasswordFormVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <AuthCardHeading\n id={titleId}\n title={\n showingForm\n ? (title ?? t('resetPasswordForm.title'))\n : t('resetPasswordForm.pageTitle')\n }\n description={\n showingForm\n ? (description ?? t('resetPasswordForm.description'))\n : undefined\n }\n level={headingLevel}\n showLogo={showLogo}\n logoMotion={logoMotion}\n />\n\n {children ? (\n <div\n data-slot=\"host-content\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {children}\n </div>\n ) : null}\n\n {state === 'done' && (\n <>\n <Alert\n ref={result}\n variant=\"success\"\n tabIndex={-1}\n aria-labelledby={resultTitleId}\n aria-describedby={resultDescriptionId}\n data-slot=\"result\"\n className={resultVariants()}\n >\n <Alert.Title id={resultTitleId} as={resultHeading}>\n {t('resetPasswordForm.doneTitle')}\n </Alert.Title>\n <Alert.Description id={resultDescriptionId}>\n {email\n ? t('resetPasswordForm.doneDescriptionEmail', {\n // Isolated left to right, so the address keeps its\n // order inside a right-to-left sentence.\n email: `${LTR_ISOLATE}${email}${POP_ISOLATE}`,\n })\n : t('resetPasswordForm.doneDescription')}\n </Alert.Description>\n </Alert>\n {loginLink && (\n <Button\n asChild\n intent=\"primary\"\n size=\"lg\"\n className=\"ds:w-full\"\n >\n <a href={loginLink} data-action=\"login\">\n {t('resetPasswordForm.signIn')}\n </a>\n </Button>\n )}\n </>\n )}\n\n {state === 'expired' && (\n <>\n <Alert\n ref={result}\n variant=\"warning\"\n // Focus moves here: an assertive alert as well would read\n // it twice, and over a page that opens on it.\n announce=\"polite\"\n tabIndex={-1}\n aria-labelledby={resultTitleId}\n aria-describedby={resultDescriptionId}\n data-slot=\"result\"\n className={resultVariants()}\n >\n <Alert.Title id={resultTitleId} as={resultHeading}>\n {t('resetPasswordForm.expiredTitle')}\n </Alert.Title>\n <Alert.Description id={resultDescriptionId}>\n {t('resetPasswordForm.expiredDescription')}\n </Alert.Description>\n </Alert>\n {requestLink && (\n <Button\n asChild\n intent=\"primary\"\n size=\"lg\"\n className=\"ds:w-full\"\n >\n <a href={requestLink} data-action=\"request-link\">\n {t('resetPasswordForm.requestLink')}\n </a>\n </Button>\n )}\n </>\n )}\n\n {showingForm && (\n <>\n <form\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <ErrorSummary\n ref={summary.ref}\n headingLevel={(headingLevel + 1) as 2 | 3 | 4}\n // The message about the whole form is read with it.\n aria-describedby={\n serverErrors.form ? formMessageId : undefined\n }\n errors={summary.listed.map((field) => ({\n field,\n message: errorFor(field) ?? '',\n targetId: fieldIds[field],\n }))}\n />\n\n {serverErrors.form && (\n <AuthFormMessage\n ref={formMessage}\n id={formMessageId}\n announce={formMessageAnnounce}\n >\n {serverErrors.form}\n </AuthFormMessage>\n )}\n\n {email ? (\n <FormField\n id={emailFieldId}\n label={t('resetPasswordForm.email')}\n data-field=\"email\"\n >\n {/* Read-only, and not posted: it has no name. `username`\n is what password managers pair with\n `new-password`, so the new password is saved under\n this address. */}\n <EmailInput\n ref={emailField.ref}\n name=\"\"\n readOnly\n autoComplete=\"username\"\n // An address reads left to right in any language.\n dir=\"ltr\"\n disableBuiltInValidation\n onChange={emailField.quiet()}\n />\n </FormField>\n ) : null}\n\n <FormField\n id={passwordFieldId}\n label={labels.password}\n required\n error={errorFor('password')}\n announceError={!summary.lists('password')}\n data-field=\"password\"\n >\n {/* PasswordInput names itself \"password\" when given no\n name; an empty one keeps a field out of the post. */}\n <PasswordInput\n ref={control.password}\n name={name('password')}\n autoComplete=\"new-password\"\n requirements={requirements}\n value={values.password}\n onChange={(event) => set('password', event.target.value)}\n onBlur={() => leave('password')}\n />\n </FormField>\n\n <FormField\n id={passwordConfirmFieldId}\n label={labels.passwordConfirm}\n required\n error={errorFor('passwordConfirm')}\n announceError={!summary.lists('passwordConfirm')}\n data-field=\"passwordConfirm\"\n >\n <PasswordInput\n ref={control.passwordConfirm}\n name={name('passwordConfirm')}\n autoComplete=\"new-password\"\n value={values.passwordConfirm}\n onChange={(event) =>\n set('passwordConfirm', event.target.value)\n }\n onBlur={() => {\n leave('passwordConfirm');\n match.confirmProps.onBlur();\n }}\n />\n </FormField>\n\n <ExtraFields fields={extraFields} />\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('resetPasswordForm.submit')}\n </Button>\n </form>\n {/* Outside the form: a screen reader may hold back what\n changes inside a busy region. */}\n <AuthFormStatus busy={busy} />\n </>\n )}\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nResetPasswordForm.displayName = 'ResetPasswordForm';\n"],"names":["PLATFORM_PASSWORD_POLICY","RESET_PASSWORD_FORM_FIELDS","resetPasswordFormVariants","cva","resultVariants","LTR_ISOLATE","POP_ISOLATE","RESULT_HEADING","hasMessage","errors","focusTargetFor","messages","field","ResetPasswordForm","forwardRef","state","title","description","headingLevel","showLogo","logoMotion","children","email","loginHref","requestHref","submitLabel","submitting","onSubmit","fieldNames","action","hiddenFields","className","rest","ref","t","useTranslation","titleId","useId","resultTitleId","resultDescriptionId","emailFieldId","passwordFieldId","passwordConfirmFieldId","formMessageId","native","fieldIds","values","setValues","useState","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","set","value","previous","leave","emptyPasswords","requirements","usePasswordRequirements","match","useFieldMatch","invalid","rule","due","ownErrors","errorFor","controls","useRef","control","useMemo","node","formMessage","result","emailInput","emailField","useStateBackedInput","openedWithFieldMessage","summary","useErrorSummary","formMessageAnnounce","useFormMessageAnnounce","focusRequest","setFocusRequest","target","useEffect","_a","_b","clearOnResult","wasForm","submit","useRegistrationSubmit","answer","next","busy","formAction","useFormAction","extraFields","useExtraFields","name","safe","href","isSafeHref","loginLink","requestLink","showingForm","labels","resultHeading","jsx","Card","AuthCardHeading","jsxs","Fragment","Alert","Button","ErrorSummary","AuthFormMessage","FormField","EmailInput","PasswordInput","event","ExtraFields","AuthFormStatus"],"mappings":"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"}
@@ -3,11 +3,12 @@ import { forwardRef as Ke, useId as G, useState as f, useRef as I, useEffect as
3
3
  import { useTranslation as Je } from "react-i18next";
4
4
  import { c as Qe } from "./index-D2ZczOXr.js";
5
5
  import { parsePhoneNumberFromString as Xe } from "libphonenumber-js/min";
6
- import { i as Ye, E as pe } from "./email-input-BEO3vonE.js";
6
+ import { i as Ye } from "./isEmail-BfVspSvV.js";
7
7
  import { A as h } from "./alert-C4WKViaS.js";
8
- import { B as he } from "./button-DohK_Ak_.js";
8
+ import { B as pe } from "./button-DohK_Ak_.js";
9
9
  import { C as B } from "./card-C85_Ndhb.js";
10
10
  import { D as Ze } from "./date-picker-CdhXlgVI.js";
11
+ import { E as he } from "./email-input-DxwbREpx.js";
11
12
  import { E as Ve } from "./error-summary-DxNhwf_G.js";
12
13
  import { F } from "./form-field-CyHfOVKF.js";
13
14
  import { P as ue } from "./phone-input-BL8Sj6OG.js";
@@ -180,7 +181,7 @@ const q = [
180
181
  date: _(ce)
181
182
  }) })
182
183
  ] }),
183
- de && /* @__PURE__ */ n(he, { asChild: !0, intent: "secondary", "data-action": "send-another", children: /* @__PURE__ */ n("a", { href: de, children: i("sendRegistrationLink.sendAnother") }) })
184
+ de && /* @__PURE__ */ n(pe, { asChild: !0, intent: "secondary", "data-action": "send-another", children: /* @__PURE__ */ n("a", { href: de, children: i("sendRegistrationLink.sendAnother") }) })
184
185
  ] }) })
185
186
  }
186
187
  ) : /* @__PURE__ */ n(
@@ -247,7 +248,7 @@ const q = [
247
248
  announceError: !s.lists("email"),
248
249
  "data-field": "email",
249
250
  children: /* @__PURE__ */ n(
250
- pe,
251
+ he,
251
252
  {
252
253
  ref: te.ref,
253
254
  name: le("email"),
@@ -271,7 +272,7 @@ const q = [
271
272
  announceError: !s.lists("emailConfirm"),
272
273
  "data-field": "emailConfirm",
273
274
  children: /* @__PURE__ */ n(
274
- pe,
275
+ he,
275
276
  {
276
277
  ref: ie.ref,
277
278
  name: le("emailConfirm"),
@@ -381,7 +382,7 @@ const q = [
381
382
  ),
382
383
  He.map(([e, o]) => /* @__PURE__ */ n("input", { type: "hidden", name: e, value: o }, e)),
383
384
  /* @__PURE__ */ n(
384
- he,
385
+ pe,
385
386
  {
386
387
  type: "submit",
387
388
  intent: "primary",
@@ -406,4 +407,4 @@ export {
406
407
  q as S,
407
408
  fn as a
408
409
  };
409
- //# sourceMappingURL=send-registration-link-form-Nn0jf65G.js.map
410
+ //# sourceMappingURL=send-registration-link-form-OgPomrZN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"send-registration-link-form-Nn0jf65G.js","sources":["../../src/patterns/send-registration-link-form/send-registration-link-form.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* SendRegistrationLinkForm: the form sales use in the admin area to */\n/* send a doctor a registration link. */\n/* */\n/* Email, confirm email, mobile phone, confirm phone and the last day the link allows */\n/* login. Every prop is data, so a server-rendered page can mount it */\n/* from JSON. The browser posts a real form to the host's own field */\n/* names; the card checks what a browser can check first. The host */\n/* keeps every server rule. The link itself is never shown. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport {\n format,\n isAfter,\n isBefore,\n isValid,\n parseISO,\n startOfDay,\n} from 'date-fns';\nimport { parsePhoneNumberFromString } from 'libphonenumber-js/min';\nimport isEmail from 'validator/lib/isEmail';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { DatePicker } from '../../components/date-picker';\nimport { EmailInput } from '../../components/email-input';\nimport { ErrorSummary } from '../../components/error-summary';\nimport { FormField } from '../../components/form-field';\nimport { PhoneInput } from '../../components/phone-input';\nimport { isSafeHref, isSameSiteHref } from '../../components/_shared/safe-href';\nimport { useStateBackedInput } from '../../components/_shared/use-state-backed-input';\nimport { useFieldMatch } from '../../hooks/use-field-match';\nimport {\n useErrorSummary,\n useFormMessageAnnounce,\n} from '../_shared/use-error-summary';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The fields of the form, in the order they appear. */\nexport const SEND_REGISTRATION_LINK_FIELDS = [\n 'email',\n 'emailConfirm',\n 'phone',\n 'phoneConfirm',\n 'allowLoginUntil',\n] as const;\n\nexport type SendRegistrationLinkField =\n (typeof SEND_REGISTRATION_LINK_FIELDS)[number];\n\n/** What `onSubmit` receives once every check has passed. */\nexport interface SendRegistrationLinkValues {\n email: string;\n /** As typed. It matches `email` apart from case and outer spaces. */\n emailConfirm: string;\n /** In E.164 form, e.g. `+393331234567`. */\n phone: string;\n /** In E.164 form. Equal to `phone`. */\n phoneConfirm: string;\n /** `yyyy-MM-dd`. */\n allowLoginUntil: string;\n}\n\n/** Values to show when the form opens, e.g. after a refused post.\n * `allowLoginUntil` is `yyyy-MM-dd`. */\nexport type SendRegistrationLinkInitialValues =\n Partial<SendRegistrationLinkValues>;\n\n/** Messages from the server, already translated by the host: one per\n * field, plus `form` for a message about the whole form. */\nexport type SendRegistrationLinkErrors = Partial<\n Record<SendRegistrationLinkField | 'form', string>\n>;\n\n/** The host's own form field names, e.g. `send_registration_link[email]`. */\nexport type SendRegistrationLinkFieldNames = Partial<\n Record<SendRegistrationLinkField, string>\n>;\n\n/** Guidance for the person sending, in the host's own words. */\nexport interface SendRegistrationLinkGuidance {\n /** The notice's heading. Pass it translated. */\n title: string;\n /** One short point each. Pass them translated. Plain text. */\n points: readonly string[];\n}\n\n/** The result of a send, shown instead of the form. */\nexport interface SendRegistrationLinkSent {\n /** The address the email went to. */\n email: string;\n /** The last day the link allows login, `yyyy-MM-dd`. */\n allowLoginUntil: string;\n}\n\nexport interface SendRegistrationLinkFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /** Replaces the heading \"Send a registration link\". Pass it translated. */\n title?: string;\n /** The heading's level. Default 2, for a page that has its own `h1`. */\n headingLevel?: 1 | 2 | 3;\n /** A warning-style notice above the form. The kit has no copy for it. */\n guidance?: SendRegistrationLinkGuidance;\n /** The first day that can be chosen, `yyyy-MM-dd`. Default: tomorrow. */\n minDate?: string;\n /** The last day that can be chosen, `yyyy-MM-dd`. Default: no limit.\n * Keep it equal to the server's. */\n maxDate?: string;\n /** Values to show when the form opens. Read once. */\n initialValues?: SendRegistrationLinkInitialValues;\n /** Messages from the server. Each shows on its field until the user\n * changes that field, and the form takes focus when they are present\n * at load. */\n errors?: SendRegistrationLinkErrors;\n /** Fields that refuse paste, so the user types them. Default: none.\n * Refusing a paste in `phoneConfirm` is silent: use it with care. */\n blockPaste?: readonly ('email' | 'emailConfirm' | 'phoneConfirm')[];\n /** Replaces the button's \"Send registration link\". Translated. */\n submitLabel?: string;\n /** True while a React host sends the values. */\n submitting?: boolean;\n /** Shows the result instead of the form. */\n sent?: SendRegistrationLinkSent;\n /** Where \"Send another link\" leads. Same-site path or full address. */\n sendAnotherHref?: string;\n /** For a native form post: the host's field names. When set, the\n * browser posts the form. */\n fieldNames?: SendRegistrationLinkFieldNames;\n /** Where the post goes. Default: the current address. Same site only. */\n action?: string;\n /** Extra hidden inputs for a native post, by name: the CSRF token. */\n hiddenFields?: Readonly<Record<string, string>>;\n /** For React hosts: called once every check has passed. Not called when\n * `fieldNames` is set. */\n onSubmit?: (values: SendRegistrationLinkValues) => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n 'ds:w-full ds:[max-inline-size:36rem] ds:text-start ds:text-[var(--foreground)]',\n);\n\nconst isoDay = (date: Date): string => format(date, 'yyyy-MM-dd');\n\n/** A `yyyy-MM-dd` string as a local date, or nothing. */\nconst readDay = (value: string | undefined): Date | undefined => {\n if (!value) return undefined;\n const day = parseISO(value);\n return isValid(day) ? startOfDay(day) : undefined;\n};\n\nconst isPossiblePhone = (e164: string): boolean =>\n parsePhoneNumberFromString(e164)?.isPossible() ?? false;\n\nconst hasMessage = (errors: SendRegistrationLinkErrors): boolean =>\n Object.values(errors).some(Boolean);\n\n/* -------------------------------------------------------------------- */\n/* SendRegistrationLinkForm */\n/* -------------------------------------------------------------------- */\n\nexport const SendRegistrationLinkForm = forwardRef<\n HTMLDivElement,\n SendRegistrationLinkFormProps\n>(\n (\n {\n title,\n headingLevel = 2,\n guidance,\n minDate,\n maxDate,\n initialValues,\n errors,\n blockPaste,\n submitLabel,\n submitting = false,\n sent,\n sendAnotherHref,\n fieldNames,\n action,\n hiddenFields,\n onSubmit,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const titleId = useId();\n const fieldIdBase = useId();\n const fieldId = (field: SendRegistrationLinkField) =>\n `${fieldIdBase}-${field}`;\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n const Heading = `h${headingLevel}` as const;\n\n // The allowed days, whole days in the visitor's time zone. The default\n // first day is tomorrow, worked out once.\n const [tomorrow] = useState(() => {\n const day = startOfDay(new Date());\n day.setDate(day.getDate() + 1);\n return day;\n });\n const first = readDay(minDate) ?? tomorrow;\n const last = readDay(maxDate);\n const inRange = (day: Date) =>\n !isBefore(day, first) && !(last && isAfter(day, last));\n\n /* ------------------------------ State ----------------------------- */\n\n const [values, setValues] = useState(() => ({\n email: initialValues?.email ?? '',\n emailConfirm: initialValues?.emailConfirm ?? '',\n phone: initialValues?.phone ?? '',\n phoneConfirm: initialValues?.phoneConfirm ?? '',\n }));\n const [day, setDay] = useState<Date | undefined>(() =>\n readDay(initialValues?.allowLoginUntil),\n );\n const [phonePossible, setPhonePossible] = useState(() =>\n isPossiblePhone(initialValues?.phone ?? ''),\n );\n const [touched, setTouched] = useState<\n Partial<Record<SendRegistrationLinkField, boolean>>\n >(() => ({ email: Boolean(initialValues?.email) }));\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] =\n useState<SendRegistrationLinkErrors>(() => errors ?? {});\n\n const clearServer = (field: SendRegistrationLinkField) =>\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n const set = (\n field: 'email' | 'emailConfirm' | 'phone' | 'phoneConfirm',\n value: string,\n ) => {\n setValues((previous) => ({ ...previous, [field]: value }));\n clearServer(field);\n };\n const leave = (field: SendRegistrationLinkField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n\n /* ---------------------------- Validation -------------------------- */\n\n // The same comparison the server makes: trimmed, ignoring case.\n const emailMatch = useFieldMatch({\n value: values.email,\n confirmValue: values.emailConfirm,\n kind: 'email',\n submitted,\n });\n\n // Both phones are E.164 values, the ones the form posts.\n const phoneMatch = useFieldMatch({\n value: values.phone,\n confirmValue: values.phoneConfirm,\n kind: 'phone',\n submitted,\n });\n\n const invalid: Record<SendRegistrationLinkField, boolean> = {\n email: !isEmail(values.email),\n emailConfirm: values.emailConfirm === '' || !emailMatch.matches,\n phone: values.phone === '' || !phonePossible,\n phoneConfirm: values.phoneConfirm === '' || !phoneMatch.matches,\n allowLoginUntil: !day || !inRange(day),\n };\n const required = t('registrationForm.required');\n const formatDay = (value: Date) =>\n new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }).format(\n value,\n );\n const labels: Record<SendRegistrationLinkField, string> = {\n email: t('registrationForm.email'),\n emailConfirm: t('registrationForm.emailConfirm'),\n phone: t('sendRegistrationLink.phone'),\n phoneConfirm: t('sendRegistrationLink.phoneConfirm'),\n allowLoginUntil: t('sendRegistrationLink.allowLoginUntil'),\n };\n // A message shows once the user has left the field or tried to submit.\n // A date waits for a submit, or a value out of range: leaving the\n // field to open the calendar is not a mistake.\n const due = (field: SendRegistrationLinkField) =>\n submitted ||\n (field === 'allowLoginUntil'\n ? day !== undefined\n : touched[field] === true);\n const whenDue = (field: SendRegistrationLinkField, message: string) =>\n due(field) && invalid[field] ? message : undefined;\n const ownErrors: Record<SendRegistrationLinkField, string | undefined> = {\n email: whenDue(\n 'email',\n values.email === '' ? required : t('inputs.email.invalid'),\n ),\n emailConfirm:\n values.emailConfirm === ''\n ? whenDue('emailConfirm', required)\n : emailMatch.error,\n phone: whenDue(\n 'phone',\n values.phone === '' ? required : t('registrationForm.phoneInvalid'),\n ),\n phoneConfirm:\n values.phoneConfirm === ''\n ? whenDue('phoneConfirm', required)\n : phoneMatch.error,\n allowLoginUntil: whenDue(\n 'allowLoginUntil',\n !day\n ? required\n : t('sendRegistrationLink.dateOutOfRange', {\n min: formatDay(first),\n max: last ? formatDay(last) : '…',\n }),\n ),\n };\n const errorFor = (field: SendRegistrationLinkField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n const form = useRef<HTMLFormElement>(null);\n const formMessage = useRef<HTMLDivElement>(null);\n const emailRef = useRef<HTMLInputElement | null>(null);\n const emailConfirmRef = useRef<HTMLInputElement | null>(null);\n // The addresses stay out of the inputs' `value` attributes.\n const emailField = useStateBackedInput(values.email, emailRef);\n const emailConfirmField = useStateBackedInput(\n values.emailConfirm,\n emailConfirmRef,\n );\n\n const focusField = (field: SendRegistrationLinkField | 'form') => {\n if (field === 'form') {\n formMessage.current?.focus();\n return;\n }\n form.current\n ?.querySelector<HTMLElement>(`[data-field=\"${field}\"] input`)\n ?.focus();\n };\n const focusTargetFor = (messages: SendRegistrationLinkErrors) =>\n SEND_REGISTRATION_LINK_FIELDS.find((field) => messages[field]) ??\n (hasMessage(messages) ? ('form' as const) : undefined);\n\n const [openedWithFieldMessage] = useState(() =>\n SEND_REGISTRATION_LINK_FIELDS.some((field) => Boolean(errors?.[field])),\n );\n const summary = useErrorSummary(\n SEND_REGISTRATION_LINK_FIELDS,\n errorFor,\n openedWithFieldMessage,\n );\n const [focusRequest, setFocusRequest] = useState<{\n target: SendRegistrationLinkField | 'form';\n } | null>(() => {\n const target = openedWithFieldMessage\n ? undefined\n : focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (focusRequest) focusField(focusRequest.target);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [focusRequest]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<SendRegistrationLinkField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () =>\n SEND_REGISTRATION_LINK_FIELDS.find((field) => invalid[field]),\n onRefused: (field) => {\n setSubmitted(true);\n summary.open(() => setFocusRequest({ target: field }));\n },\n deliver: () =>\n onSubmit?.({\n ...values,\n allowLoginUntil: day ? isoDay(day) : '',\n }),\n onAnswer: (answer) => {\n const next: SendRegistrationLinkErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n setSubmitted(false);\n summary.open(() => {\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n });\n },\n });\n\n /* ------------------------------ Render ---------------------------- */\n\n const name = (field: SendRegistrationLinkField) =>\n native ? fieldNames[field] : field;\n const formAction =\n native && action && isSameSiteHref(action) ? action : undefined;\n const formError = serverErrors.form;\n const formMessageAnnounce = useFormMessageAnnounce(\n formError,\n summary.listed.length > 0,\n );\n const ownNames = new Set(Object.values(fieldNames ?? {}));\n const extraFields = native\n ? Object.entries(hiddenFields ?? {}).filter(\n ([extra]) => !ownNames.has(extra),\n )\n : [];\n const anotherLink =\n sendAnotherHref && isSafeHref(sendAnotherHref)\n ? sendAnotherHref\n : undefined;\n const sentDay = readDay(sent?.allowLoginUntil);\n\n if (sent) {\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"send-registration-link-form\"\n data-state=\"sent\"\n className={rootVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <Heading className=\"type-title-card\">\n {title ?? t('sendRegistrationLink.title')}\n </Heading>\n <Alert variant=\"success\" data-slot=\"sent\">\n <Alert.Title as=\"p\">\n {t('sendRegistrationLink.sentTitle')}\n </Alert.Title>\n <Alert.Description>\n {t('sendRegistrationLink.sentEmail', { email: sent.email })}\n </Alert.Description>\n {sentDay && (\n <Alert.Description>\n {t('sendRegistrationLink.sentUntil', {\n date: formatDay(sentDay),\n })}\n </Alert.Description>\n )}\n </Alert>\n {anotherLink && (\n <Button asChild intent=\"secondary\" data-action=\"send-another\">\n <a href={anotherLink}>\n {t('sendRegistrationLink.sendAnother')}\n </a>\n </Button>\n )}\n </Card.Body>\n </Card>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"send-registration-link-form\"\n className={rootVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <Heading id={titleId} className=\"type-title-card\">\n {title ?? t('sendRegistrationLink.title')}\n </Heading>\n\n {guidance && (\n <Alert variant=\"warning\" data-slot=\"guidance\">\n <Alert.Title as=\"p\">{guidance.title}</Alert.Title>\n <ul className=\"ds:mx-0 ds:mb-0 ds:mt-[var(--spacing-xs)] ds:ps-[var(--spacing-lg)] ds:list-disc type-body-sm\">\n {guidance.points.map((point) => (\n <li key={point}>{point}</li>\n ))}\n </ul>\n </Alert>\n )}\n\n <form\n ref={form}\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={submit.busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <ErrorSummary\n ref={summary.ref}\n headingLevel={(headingLevel + 1) as 2 | 3 | 4}\n aria-describedby={formError ? formMessageId : undefined}\n errors={summary.listed.map((field) => {\n const message = errorFor(field) ?? '';\n return {\n field,\n message,\n label: message === required ? labels[field] : undefined,\n targetId: fieldId(field),\n };\n })}\n />\n\n {formError && (\n <Alert\n ref={formMessage}\n id={formMessageId}\n variant=\"error\"\n announce={formMessageAnnounce}\n tabIndex={-1}\n data-field=\"form\"\n >\n <Alert.Description>{formError}</Alert.Description>\n </Alert>\n )}\n\n <FormField\n id={fieldId('email')}\n label={labels.email}\n required\n error={errorFor('email')}\n announceError={!summary.lists('email')}\n data-field=\"email\"\n >\n <EmailInput\n ref={emailField.ref}\n name={name('email')}\n errorMessage={null}\n onChange={emailField.quiet((event) =>\n set('email', event.target.value),\n )}\n onBlur={() => leave('email')}\n blockPaste={blockPaste?.includes('email') ?? false}\n />\n </FormField>\n\n <FormField\n id={fieldId('emailConfirm')}\n label={labels.emailConfirm}\n required\n error={errorFor('emailConfirm')}\n announceError={!summary.lists('emailConfirm')}\n data-field=\"emailConfirm\"\n >\n <EmailInput\n ref={emailConfirmField.ref}\n name={name('emailConfirm')}\n disableBuiltInValidation\n onChange={emailConfirmField.quiet((event) =>\n set('emailConfirm', event.target.value),\n )}\n onBlur={() => {\n leave('emailConfirm');\n emailMatch.confirmProps.onBlur();\n }}\n blockPaste={blockPaste?.includes('emailConfirm') ?? false}\n />\n </FormField>\n\n <FormField\n id={fieldId('phone')}\n label={labels.phone}\n required\n description={t('sendRegistrationLink.phoneDescription')}\n error={errorFor('phone')}\n announceError={!summary.lists('phone')}\n data-field=\"phone\"\n onBlur={() => leave('phone')}\n >\n {/* The visible input holds the number as typed; a hidden\n input carries the full international number. */}\n <PhoneInput\n name={native ? undefined : 'phone'}\n value={values.phone}\n onChange={(e164, meta) => {\n set('phone', e164);\n setPhonePossible(meta.isPossible);\n }}\n />\n </FormField>\n\n <FormField\n id={fieldId('phoneConfirm')}\n label={labels.phoneConfirm}\n required\n error={errorFor('phoneConfirm')}\n announceError={!summary.lists('phoneConfirm')}\n data-field=\"phoneConfirm\"\n onBlur={() => {\n leave('phoneConfirm');\n phoneMatch.confirmProps.onBlur();\n }}\n onPasteCapture={\n blockPaste?.includes('phoneConfirm')\n ? (event) => event.preventDefault()\n : undefined\n }\n >\n <PhoneInput\n name={native ? undefined : 'phoneConfirm'}\n value={values.phoneConfirm}\n onChange={(e164) => set('phoneConfirm', e164)}\n />\n </FormField>\n\n <FormField\n id={fieldId('allowLoginUntil')}\n label={labels.allowLoginUntil}\n required\n error={errorFor('allowLoginUntil')}\n announceError={!summary.lists('allowLoginUntil')}\n data-field=\"allowLoginUntil\"\n >\n <DatePicker\n value={day}\n minDate={first}\n maxDate={last}\n onChange={(next) => {\n setDay(next);\n clearServer('allowLoginUntil');\n }}\n />\n </FormField>\n\n {native && fieldNames.phone && (\n <input\n type=\"hidden\"\n name={fieldNames.phone}\n value={values.phone}\n />\n )}\n {native && fieldNames.phoneConfirm && (\n <input\n type=\"hidden\"\n name={fieldNames.phoneConfirm}\n value={values.phoneConfirm}\n />\n )}\n {native && fieldNames.allowLoginUntil && (\n <input\n type=\"hidden\"\n name={fieldNames.allowLoginUntil}\n value={day ? isoDay(day) : ''}\n />\n )}\n {extraFields.map(([extra, value]) => (\n <input key={extra} type=\"hidden\" name={extra} value={value} />\n ))}\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={submit.busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('sendRegistrationLink.submit')}\n </Button>\n <p role=\"status\" className=\"ds:sr-only\">\n {submit.busy ? t('chat.message.status.sending') : ''}\n </p>\n </form>\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nSendRegistrationLinkForm.displayName = 'SendRegistrationLinkForm';\n"],"names":["SEND_REGISTRATION_LINK_FIELDS","rootVariants","cva","isoDay","date","format","readDay","value","day","parseISO","isValid","startOfDay","isPossiblePhone","e164","_a","parsePhoneNumberFromString","hasMessage","errors","SendRegistrationLinkForm","forwardRef","title","headingLevel","guidance","minDate","maxDate","initialValues","blockPaste","submitLabel","submitting","sent","sendAnotherHref","fieldNames","action","hiddenFields","onSubmit","className","rest","ref","t","i18n","useTranslation","titleId","useId","fieldIdBase","fieldId","field","formMessageId","native","Heading","tomorrow","useState","first","last","inRange","isBefore","isAfter","values","setValues","setDay","phonePossible","setPhonePossible","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","clearServer","previous","set","leave","emailMatch","useFieldMatch","phoneMatch","invalid","isEmail","required","formatDay","labels","due","whenDue","message","ownErrors","errorFor","form","useRef","formMessage","emailRef","emailConfirmRef","emailField","useStateBackedInput","emailConfirmField","focusField","_c","_b","focusTargetFor","messages","openedWithFieldMessage","summary","useErrorSummary","focusRequest","setFocusRequest","target","useEffect","submit","useRegistrationSubmit","answer","next","name","formAction","isSameSiteHref","formError","formMessageAnnounce","useFormMessageAnnounce","ownNames","extraFields","extra","anotherLink","isSafeHref","sentDay","jsx","Card","jsxs","Alert","Button","point","ErrorSummary","FormField","EmailInput","event","PhoneInput","meta","DatePicker"],"mappings":"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"}
1
+ {"version":3,"file":"send-registration-link-form-OgPomrZN.js","sources":["../../src/patterns/send-registration-link-form/send-registration-link-form.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* SendRegistrationLinkForm: the form sales use in the admin area to */\n/* send a doctor a registration link. */\n/* */\n/* Email, confirm email, mobile phone, confirm phone and the last day the link allows */\n/* login. Every prop is data, so a server-rendered page can mount it */\n/* from JSON. The browser posts a real form to the host's own field */\n/* names; the card checks what a browser can check first. The host */\n/* keeps every server rule. The link itself is never shown. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport {\n format,\n isAfter,\n isBefore,\n isValid,\n parseISO,\n startOfDay,\n} from 'date-fns';\nimport { parsePhoneNumberFromString } from 'libphonenumber-js/min';\nimport isEmail from 'validator/lib/isEmail';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { DatePicker } from '../../components/date-picker';\nimport { EmailInput } from '../../components/email-input';\nimport { ErrorSummary } from '../../components/error-summary';\nimport { FormField } from '../../components/form-field';\nimport { PhoneInput } from '../../components/phone-input';\nimport { isSafeHref, isSameSiteHref } from '../../components/_shared/safe-href';\nimport { useStateBackedInput } from '../../components/_shared/use-state-backed-input';\nimport { useFieldMatch } from '../../hooks/use-field-match';\nimport {\n useErrorSummary,\n useFormMessageAnnounce,\n} from '../_shared/use-error-summary';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The fields of the form, in the order they appear. */\nexport const SEND_REGISTRATION_LINK_FIELDS = [\n 'email',\n 'emailConfirm',\n 'phone',\n 'phoneConfirm',\n 'allowLoginUntil',\n] as const;\n\nexport type SendRegistrationLinkField =\n (typeof SEND_REGISTRATION_LINK_FIELDS)[number];\n\n/** What `onSubmit` receives once every check has passed. */\nexport interface SendRegistrationLinkValues {\n email: string;\n /** As typed. It matches `email` apart from case and outer spaces. */\n emailConfirm: string;\n /** In E.164 form, e.g. `+393331234567`. */\n phone: string;\n /** In E.164 form. Equal to `phone`. */\n phoneConfirm: string;\n /** `yyyy-MM-dd`. */\n allowLoginUntil: string;\n}\n\n/** Values to show when the form opens, e.g. after a refused post.\n * `allowLoginUntil` is `yyyy-MM-dd`. */\nexport type SendRegistrationLinkInitialValues =\n Partial<SendRegistrationLinkValues>;\n\n/** Messages from the server, already translated by the host: one per\n * field, plus `form` for a message about the whole form. */\nexport type SendRegistrationLinkErrors = Partial<\n Record<SendRegistrationLinkField | 'form', string>\n>;\n\n/** The host's own form field names, e.g. `send_registration_link[email]`. */\nexport type SendRegistrationLinkFieldNames = Partial<\n Record<SendRegistrationLinkField, string>\n>;\n\n/** Guidance for the person sending, in the host's own words. */\nexport interface SendRegistrationLinkGuidance {\n /** The notice's heading. Pass it translated. */\n title: string;\n /** One short point each. Pass them translated. Plain text. */\n points: readonly string[];\n}\n\n/** The result of a send, shown instead of the form. */\nexport interface SendRegistrationLinkSent {\n /** The address the email went to. */\n email: string;\n /** The last day the link allows login, `yyyy-MM-dd`. */\n allowLoginUntil: string;\n}\n\nexport interface SendRegistrationLinkFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /** Replaces the heading \"Send a registration link\". Pass it translated. */\n title?: string;\n /** The heading's level. Default 2, for a page that has its own `h1`. */\n headingLevel?: 1 | 2 | 3;\n /** A warning-style notice above the form. The kit has no copy for it. */\n guidance?: SendRegistrationLinkGuidance;\n /** The first day that can be chosen, `yyyy-MM-dd`. Default: tomorrow. */\n minDate?: string;\n /** The last day that can be chosen, `yyyy-MM-dd`. Default: no limit.\n * Keep it equal to the server's. */\n maxDate?: string;\n /** Values to show when the form opens. Read once. */\n initialValues?: SendRegistrationLinkInitialValues;\n /** Messages from the server. Each shows on its field until the user\n * changes that field, and the form takes focus when they are present\n * at load. */\n errors?: SendRegistrationLinkErrors;\n /** Fields that refuse paste, so the user types them. Default: none.\n * Refusing a paste in `phoneConfirm` is silent: use it with care. */\n blockPaste?: readonly ('email' | 'emailConfirm' | 'phoneConfirm')[];\n /** Replaces the button's \"Send registration link\". Translated. */\n submitLabel?: string;\n /** True while a React host sends the values. */\n submitting?: boolean;\n /** Shows the result instead of the form. */\n sent?: SendRegistrationLinkSent;\n /** Where \"Send another link\" leads. Same-site path or full address. */\n sendAnotherHref?: string;\n /** For a native form post: the host's field names. When set, the\n * browser posts the form. */\n fieldNames?: SendRegistrationLinkFieldNames;\n /** Where the post goes. Default: the current address. Same site only. */\n action?: string;\n /** Extra hidden inputs for a native post, by name: the CSRF token. */\n hiddenFields?: Readonly<Record<string, string>>;\n /** For React hosts: called once every check has passed. Not called when\n * `fieldNames` is set. */\n onSubmit?: (values: SendRegistrationLinkValues) => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n 'ds:w-full ds:[max-inline-size:36rem] ds:text-start ds:text-[var(--foreground)]',\n);\n\nconst isoDay = (date: Date): string => format(date, 'yyyy-MM-dd');\n\n/** A `yyyy-MM-dd` string as a local date, or nothing. */\nconst readDay = (value: string | undefined): Date | undefined => {\n if (!value) return undefined;\n const day = parseISO(value);\n return isValid(day) ? startOfDay(day) : undefined;\n};\n\nconst isPossiblePhone = (e164: string): boolean =>\n parsePhoneNumberFromString(e164)?.isPossible() ?? false;\n\nconst hasMessage = (errors: SendRegistrationLinkErrors): boolean =>\n Object.values(errors).some(Boolean);\n\n/* -------------------------------------------------------------------- */\n/* SendRegistrationLinkForm */\n/* -------------------------------------------------------------------- */\n\nexport const SendRegistrationLinkForm = forwardRef<\n HTMLDivElement,\n SendRegistrationLinkFormProps\n>(\n (\n {\n title,\n headingLevel = 2,\n guidance,\n minDate,\n maxDate,\n initialValues,\n errors,\n blockPaste,\n submitLabel,\n submitting = false,\n sent,\n sendAnotherHref,\n fieldNames,\n action,\n hiddenFields,\n onSubmit,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const titleId = useId();\n const fieldIdBase = useId();\n const fieldId = (field: SendRegistrationLinkField) =>\n `${fieldIdBase}-${field}`;\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n const Heading = `h${headingLevel}` as const;\n\n // The allowed days, whole days in the visitor's time zone. The default\n // first day is tomorrow, worked out once.\n const [tomorrow] = useState(() => {\n const day = startOfDay(new Date());\n day.setDate(day.getDate() + 1);\n return day;\n });\n const first = readDay(minDate) ?? tomorrow;\n const last = readDay(maxDate);\n const inRange = (day: Date) =>\n !isBefore(day, first) && !(last && isAfter(day, last));\n\n /* ------------------------------ State ----------------------------- */\n\n const [values, setValues] = useState(() => ({\n email: initialValues?.email ?? '',\n emailConfirm: initialValues?.emailConfirm ?? '',\n phone: initialValues?.phone ?? '',\n phoneConfirm: initialValues?.phoneConfirm ?? '',\n }));\n const [day, setDay] = useState<Date | undefined>(() =>\n readDay(initialValues?.allowLoginUntil),\n );\n const [phonePossible, setPhonePossible] = useState(() =>\n isPossiblePhone(initialValues?.phone ?? ''),\n );\n const [touched, setTouched] = useState<\n Partial<Record<SendRegistrationLinkField, boolean>>\n >(() => ({ email: Boolean(initialValues?.email) }));\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] =\n useState<SendRegistrationLinkErrors>(() => errors ?? {});\n\n const clearServer = (field: SendRegistrationLinkField) =>\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n const set = (\n field: 'email' | 'emailConfirm' | 'phone' | 'phoneConfirm',\n value: string,\n ) => {\n setValues((previous) => ({ ...previous, [field]: value }));\n clearServer(field);\n };\n const leave = (field: SendRegistrationLinkField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n\n /* ---------------------------- Validation -------------------------- */\n\n // The same comparison the server makes: trimmed, ignoring case.\n const emailMatch = useFieldMatch({\n value: values.email,\n confirmValue: values.emailConfirm,\n kind: 'email',\n submitted,\n });\n\n // Both phones are E.164 values, the ones the form posts.\n const phoneMatch = useFieldMatch({\n value: values.phone,\n confirmValue: values.phoneConfirm,\n kind: 'phone',\n submitted,\n });\n\n const invalid: Record<SendRegistrationLinkField, boolean> = {\n email: !isEmail(values.email),\n emailConfirm: values.emailConfirm === '' || !emailMatch.matches,\n phone: values.phone === '' || !phonePossible,\n phoneConfirm: values.phoneConfirm === '' || !phoneMatch.matches,\n allowLoginUntil: !day || !inRange(day),\n };\n const required = t('registrationForm.required');\n const formatDay = (value: Date) =>\n new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }).format(\n value,\n );\n const labels: Record<SendRegistrationLinkField, string> = {\n email: t('registrationForm.email'),\n emailConfirm: t('registrationForm.emailConfirm'),\n phone: t('sendRegistrationLink.phone'),\n phoneConfirm: t('sendRegistrationLink.phoneConfirm'),\n allowLoginUntil: t('sendRegistrationLink.allowLoginUntil'),\n };\n // A message shows once the user has left the field or tried to submit.\n // A date waits for a submit, or a value out of range: leaving the\n // field to open the calendar is not a mistake.\n const due = (field: SendRegistrationLinkField) =>\n submitted ||\n (field === 'allowLoginUntil'\n ? day !== undefined\n : touched[field] === true);\n const whenDue = (field: SendRegistrationLinkField, message: string) =>\n due(field) && invalid[field] ? message : undefined;\n const ownErrors: Record<SendRegistrationLinkField, string | undefined> = {\n email: whenDue(\n 'email',\n values.email === '' ? required : t('inputs.email.invalid'),\n ),\n emailConfirm:\n values.emailConfirm === ''\n ? whenDue('emailConfirm', required)\n : emailMatch.error,\n phone: whenDue(\n 'phone',\n values.phone === '' ? required : t('registrationForm.phoneInvalid'),\n ),\n phoneConfirm:\n values.phoneConfirm === ''\n ? whenDue('phoneConfirm', required)\n : phoneMatch.error,\n allowLoginUntil: whenDue(\n 'allowLoginUntil',\n !day\n ? required\n : t('sendRegistrationLink.dateOutOfRange', {\n min: formatDay(first),\n max: last ? formatDay(last) : '…',\n }),\n ),\n };\n const errorFor = (field: SendRegistrationLinkField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n const form = useRef<HTMLFormElement>(null);\n const formMessage = useRef<HTMLDivElement>(null);\n const emailRef = useRef<HTMLInputElement | null>(null);\n const emailConfirmRef = useRef<HTMLInputElement | null>(null);\n // The addresses stay out of the inputs' `value` attributes.\n const emailField = useStateBackedInput(values.email, emailRef);\n const emailConfirmField = useStateBackedInput(\n values.emailConfirm,\n emailConfirmRef,\n );\n\n const focusField = (field: SendRegistrationLinkField | 'form') => {\n if (field === 'form') {\n formMessage.current?.focus();\n return;\n }\n form.current\n ?.querySelector<HTMLElement>(`[data-field=\"${field}\"] input`)\n ?.focus();\n };\n const focusTargetFor = (messages: SendRegistrationLinkErrors) =>\n SEND_REGISTRATION_LINK_FIELDS.find((field) => messages[field]) ??\n (hasMessage(messages) ? ('form' as const) : undefined);\n\n const [openedWithFieldMessage] = useState(() =>\n SEND_REGISTRATION_LINK_FIELDS.some((field) => Boolean(errors?.[field])),\n );\n const summary = useErrorSummary(\n SEND_REGISTRATION_LINK_FIELDS,\n errorFor,\n openedWithFieldMessage,\n );\n const [focusRequest, setFocusRequest] = useState<{\n target: SendRegistrationLinkField | 'form';\n } | null>(() => {\n const target = openedWithFieldMessage\n ? undefined\n : focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (focusRequest) focusField(focusRequest.target);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [focusRequest]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<SendRegistrationLinkField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () =>\n SEND_REGISTRATION_LINK_FIELDS.find((field) => invalid[field]),\n onRefused: (field) => {\n setSubmitted(true);\n summary.open(() => setFocusRequest({ target: field }));\n },\n deliver: () =>\n onSubmit?.({\n ...values,\n allowLoginUntil: day ? isoDay(day) : '',\n }),\n onAnswer: (answer) => {\n const next: SendRegistrationLinkErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n setSubmitted(false);\n summary.open(() => {\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n });\n },\n });\n\n /* ------------------------------ Render ---------------------------- */\n\n const name = (field: SendRegistrationLinkField) =>\n native ? fieldNames[field] : field;\n const formAction =\n native && action && isSameSiteHref(action) ? action : undefined;\n const formError = serverErrors.form;\n const formMessageAnnounce = useFormMessageAnnounce(\n formError,\n summary.listed.length > 0,\n );\n const ownNames = new Set(Object.values(fieldNames ?? {}));\n const extraFields = native\n ? Object.entries(hiddenFields ?? {}).filter(\n ([extra]) => !ownNames.has(extra),\n )\n : [];\n const anotherLink =\n sendAnotherHref && isSafeHref(sendAnotherHref)\n ? sendAnotherHref\n : undefined;\n const sentDay = readDay(sent?.allowLoginUntil);\n\n if (sent) {\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"send-registration-link-form\"\n data-state=\"sent\"\n className={rootVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <Heading className=\"type-title-card\">\n {title ?? t('sendRegistrationLink.title')}\n </Heading>\n <Alert variant=\"success\" data-slot=\"sent\">\n <Alert.Title as=\"p\">\n {t('sendRegistrationLink.sentTitle')}\n </Alert.Title>\n <Alert.Description>\n {t('sendRegistrationLink.sentEmail', { email: sent.email })}\n </Alert.Description>\n {sentDay && (\n <Alert.Description>\n {t('sendRegistrationLink.sentUntil', {\n date: formatDay(sentDay),\n })}\n </Alert.Description>\n )}\n </Alert>\n {anotherLink && (\n <Button asChild intent=\"secondary\" data-action=\"send-another\">\n <a href={anotherLink}>\n {t('sendRegistrationLink.sendAnother')}\n </a>\n </Button>\n )}\n </Card.Body>\n </Card>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"send-registration-link-form\"\n className={rootVariants({ className })}\n >\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <Heading id={titleId} className=\"type-title-card\">\n {title ?? t('sendRegistrationLink.title')}\n </Heading>\n\n {guidance && (\n <Alert variant=\"warning\" data-slot=\"guidance\">\n <Alert.Title as=\"p\">{guidance.title}</Alert.Title>\n <ul className=\"ds:mx-0 ds:mb-0 ds:mt-[var(--spacing-xs)] ds:ps-[var(--spacing-lg)] ds:list-disc type-body-sm\">\n {guidance.points.map((point) => (\n <li key={point}>{point}</li>\n ))}\n </ul>\n </Alert>\n )}\n\n <form\n ref={form}\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={submit.busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <ErrorSummary\n ref={summary.ref}\n headingLevel={(headingLevel + 1) as 2 | 3 | 4}\n aria-describedby={formError ? formMessageId : undefined}\n errors={summary.listed.map((field) => {\n const message = errorFor(field) ?? '';\n return {\n field,\n message,\n label: message === required ? labels[field] : undefined,\n targetId: fieldId(field),\n };\n })}\n />\n\n {formError && (\n <Alert\n ref={formMessage}\n id={formMessageId}\n variant=\"error\"\n announce={formMessageAnnounce}\n tabIndex={-1}\n data-field=\"form\"\n >\n <Alert.Description>{formError}</Alert.Description>\n </Alert>\n )}\n\n <FormField\n id={fieldId('email')}\n label={labels.email}\n required\n error={errorFor('email')}\n announceError={!summary.lists('email')}\n data-field=\"email\"\n >\n <EmailInput\n ref={emailField.ref}\n name={name('email')}\n errorMessage={null}\n onChange={emailField.quiet((event) =>\n set('email', event.target.value),\n )}\n onBlur={() => leave('email')}\n blockPaste={blockPaste?.includes('email') ?? false}\n />\n </FormField>\n\n <FormField\n id={fieldId('emailConfirm')}\n label={labels.emailConfirm}\n required\n error={errorFor('emailConfirm')}\n announceError={!summary.lists('emailConfirm')}\n data-field=\"emailConfirm\"\n >\n <EmailInput\n ref={emailConfirmField.ref}\n name={name('emailConfirm')}\n disableBuiltInValidation\n onChange={emailConfirmField.quiet((event) =>\n set('emailConfirm', event.target.value),\n )}\n onBlur={() => {\n leave('emailConfirm');\n emailMatch.confirmProps.onBlur();\n }}\n blockPaste={blockPaste?.includes('emailConfirm') ?? false}\n />\n </FormField>\n\n <FormField\n id={fieldId('phone')}\n label={labels.phone}\n required\n description={t('sendRegistrationLink.phoneDescription')}\n error={errorFor('phone')}\n announceError={!summary.lists('phone')}\n data-field=\"phone\"\n onBlur={() => leave('phone')}\n >\n {/* The visible input holds the number as typed; a hidden\n input carries the full international number. */}\n <PhoneInput\n name={native ? undefined : 'phone'}\n value={values.phone}\n onChange={(e164, meta) => {\n set('phone', e164);\n setPhonePossible(meta.isPossible);\n }}\n />\n </FormField>\n\n <FormField\n id={fieldId('phoneConfirm')}\n label={labels.phoneConfirm}\n required\n error={errorFor('phoneConfirm')}\n announceError={!summary.lists('phoneConfirm')}\n data-field=\"phoneConfirm\"\n onBlur={() => {\n leave('phoneConfirm');\n phoneMatch.confirmProps.onBlur();\n }}\n onPasteCapture={\n blockPaste?.includes('phoneConfirm')\n ? (event) => event.preventDefault()\n : undefined\n }\n >\n <PhoneInput\n name={native ? undefined : 'phoneConfirm'}\n value={values.phoneConfirm}\n onChange={(e164) => set('phoneConfirm', e164)}\n />\n </FormField>\n\n <FormField\n id={fieldId('allowLoginUntil')}\n label={labels.allowLoginUntil}\n required\n error={errorFor('allowLoginUntil')}\n announceError={!summary.lists('allowLoginUntil')}\n data-field=\"allowLoginUntil\"\n >\n <DatePicker\n value={day}\n minDate={first}\n maxDate={last}\n onChange={(next) => {\n setDay(next);\n clearServer('allowLoginUntil');\n }}\n />\n </FormField>\n\n {native && fieldNames.phone && (\n <input\n type=\"hidden\"\n name={fieldNames.phone}\n value={values.phone}\n />\n )}\n {native && fieldNames.phoneConfirm && (\n <input\n type=\"hidden\"\n name={fieldNames.phoneConfirm}\n value={values.phoneConfirm}\n />\n )}\n {native && fieldNames.allowLoginUntil && (\n <input\n type=\"hidden\"\n name={fieldNames.allowLoginUntil}\n value={day ? isoDay(day) : ''}\n />\n )}\n {extraFields.map(([extra, value]) => (\n <input key={extra} type=\"hidden\" name={extra} value={value} />\n ))}\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={submit.busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('sendRegistrationLink.submit')}\n </Button>\n <p role=\"status\" className=\"ds:sr-only\">\n {submit.busy ? t('chat.message.status.sending') : ''}\n </p>\n </form>\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nSendRegistrationLinkForm.displayName = 'SendRegistrationLinkForm';\n"],"names":["SEND_REGISTRATION_LINK_FIELDS","rootVariants","cva","isoDay","date","format","readDay","value","day","parseISO","isValid","startOfDay","isPossiblePhone","e164","_a","parsePhoneNumberFromString","hasMessage","errors","SendRegistrationLinkForm","forwardRef","title","headingLevel","guidance","minDate","maxDate","initialValues","blockPaste","submitLabel","submitting","sent","sendAnotherHref","fieldNames","action","hiddenFields","onSubmit","className","rest","ref","t","i18n","useTranslation","titleId","useId","fieldIdBase","fieldId","field","formMessageId","native","Heading","tomorrow","useState","first","last","inRange","isBefore","isAfter","values","setValues","setDay","phonePossible","setPhonePossible","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","clearServer","previous","set","leave","emailMatch","useFieldMatch","phoneMatch","invalid","isEmail","required","formatDay","labels","due","whenDue","message","ownErrors","errorFor","form","useRef","formMessage","emailRef","emailConfirmRef","emailField","useStateBackedInput","emailConfirmField","focusField","_c","_b","focusTargetFor","messages","openedWithFieldMessage","summary","useErrorSummary","focusRequest","setFocusRequest","target","useEffect","submit","useRegistrationSubmit","answer","next","name","formAction","isSameSiteHref","formError","formMessageAnnounce","useFormMessageAnnounce","ownNames","extraFields","extra","anotherLink","isSafeHref","sentDay","jsx","Card","jsxs","Alert","Button","point","ErrorSummary","FormField","EmailInput","event","PhoneInput","meta","DatePicker"],"mappings":"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"}
@@ -16,7 +16,7 @@ import { E as zt } from "./editable-description-KU56SP4P.js";
16
16
  import { N as Xe } from "./note-timeline-BrjHBQfx.js";
17
17
  import { P as Ot } from "./panel-header-CbtlTe85.js";
18
18
  import { P as Ge } from "./panel-subview-DCyvn-49.js";
19
- import { P as _t } from "./patient-summary-card-DtYTo9w_.js";
19
+ import { P as _t } from "./patient-summary-card-BjZErlbt.js";
20
20
  import { S as ne } from "./section-card-D1sV4Voz.js";
21
21
  import { C as nn, S as ue } from "./skeleton-tTWJpvAq.js";
22
22
  import { T as an } from "./text-area-COMVJ1yE.js";
@@ -2195,4 +2195,4 @@ export {
2195
2195
  Kn as s,
2196
2196
  _s as u
2197
2197
  };
2198
- //# sourceMappingURL=use-appointment-details-read-DYyCYI9f.js.map
2198
+ //# sourceMappingURL=use-appointment-details-read-DvK7Looa.js.map