@nxgt/material 3.45.0 → 3.47.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 (149) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +10 -3
  3. package/dist/{async-slice-D9LAUgth.js → async-slice-DlvKCKAa.js} +2 -2
  4. package/dist/{button-b_kruV_L.js → button-yaltbQmC.js} +1 -1
  5. package/dist/charts.js +3 -3
  6. package/dist/{chip-6O3t9GXt.js → chip-BqWbbr1b.js} +1 -1
  7. package/dist/{code-editor-BtDOgUET.js → code-editor-C9qBNoYb.js} +4 -4
  8. package/dist/code-editor.js +4 -4
  9. package/dist/{code-language-items-374m-OK8.js → code-language-items-DAHtfQ7W.js} +2 -2
  10. package/dist/{components-BG-BTfJP.js → components-DFPy96C3.js} +16282 -14755
  11. package/dist/components.js +26 -26
  12. package/dist/{dialog-8Ua9uuJW.js → dialog-CCCcnTIx.js} +4 -4
  13. package/dist/dnd.js +1 -1
  14. package/dist/{dropdown-menu-DJEeT1XT.js → dropdown-menu-Df8785nt.js} +1 -1
  15. package/dist/editor.js +7 -7
  16. package/dist/{empty-state-CrhrmNqn.js → empty-state-DcF4TBzi.js} +1 -1
  17. package/dist/hooks.js +28 -40
  18. package/dist/{i18n-provider-hrtFm9jD.js → i18n-provider-C0fB0sEL.js} +1 -1
  19. package/dist/i18n.js +5 -5
  20. package/dist/{icon-badge-Cpke1tCf.js → icon-badge-aJ22mKGh.js} +1 -1
  21. package/dist/lib/components/ui/display/enrolment-card/enrolment-card.d.ts +12 -0
  22. package/dist/lib/components/ui/display/enrolment-card/index.d.ts +2 -0
  23. package/dist/lib/components/ui/display/enrolment-card/partials/enrolment-header.d.ts +14 -0
  24. package/dist/lib/components/ui/display/enrolment-card/partials/enrolment-verification.d.ts +15 -0
  25. package/dist/lib/components/ui/display/enrolment-card/types.d.ts +49 -0
  26. package/dist/lib/components/ui/display/enrolment-card/use-enrolment-card-labels.d.ts +3 -0
  27. package/dist/lib/components/ui/display/index.d.ts +2 -0
  28. package/dist/lib/components/ui/display/recovery-codes-status/index.d.ts +2 -0
  29. package/dist/lib/components/ui/display/recovery-codes-status/partials/recovery-count.d.ts +11 -0
  30. package/dist/lib/components/ui/display/recovery-codes-status/recovery-codes-status.d.ts +12 -0
  31. package/dist/lib/components/ui/display/recovery-codes-status/types.d.ts +44 -0
  32. package/dist/lib/components/ui/display/recovery-codes-status/use-recovery-codes-status-labels.d.ts +3 -0
  33. package/dist/lib/components/ui/display/timeline/index.d.ts +1 -1
  34. package/dist/lib/components/ui/display/timeline/partials/timeline-day-heading.d.ts +14 -0
  35. package/dist/lib/components/ui/display/timeline/partials/timeline-empty.d.ts +8 -0
  36. package/dist/lib/components/ui/display/timeline/partials/timeline-groups.d.ts +22 -0
  37. package/dist/lib/components/ui/display/timeline/partials/timeline-item-body.d.ts +13 -0
  38. package/dist/lib/components/ui/display/timeline/partials/timeline-item-card.d.ts +5 -0
  39. package/dist/lib/components/ui/display/timeline/partials/timeline-item-rail.d.ts +8 -0
  40. package/dist/lib/components/ui/display/timeline/partials/timeline-item-time.d.ts +12 -0
  41. package/dist/lib/components/ui/display/timeline/partials/timeline-skeleton.d.ts +4 -0
  42. package/dist/lib/components/ui/display/timeline/timeline-item.d.ts +13 -2
  43. package/dist/lib/components/ui/display/timeline/timeline-marker.d.ts +12 -0
  44. package/dist/lib/components/ui/display/timeline/timeline-rows.d.ts +23 -0
  45. package/dist/lib/components/ui/display/timeline/timeline.d.ts +32 -2
  46. package/dist/lib/components/ui/display/timeline/types.d.ts +6 -0
  47. package/dist/lib/components/ui/feedback/alert/alert.d.ts +7 -1
  48. package/dist/lib/components/ui/feedback/index.d.ts +1 -0
  49. package/dist/lib/components/ui/feedback/step-up-dialog/index.d.ts +2 -0
  50. package/dist/lib/components/ui/feedback/step-up-dialog/partials/step-up-body.d.ts +15 -0
  51. package/dist/lib/components/ui/feedback/step-up-dialog/partials/step-up-footer.d.ts +22 -0
  52. package/dist/lib/components/ui/feedback/step-up-dialog/partials/step-up-header.d.ts +10 -0
  53. package/dist/lib/components/ui/feedback/step-up-dialog/step-up-dialog.d.ts +16 -0
  54. package/dist/lib/components/ui/feedback/step-up-dialog/types.d.ts +55 -0
  55. package/dist/lib/components/ui/feedback/step-up-dialog/use-step-up-labels.d.ts +3 -0
  56. package/dist/lib/components/ui/feedback/step-up-dialog/use-step-up-state.d.ts +12 -0
  57. package/dist/lib/components/ui/feedback/step-up-dialog/use-title-focus.d.ts +5 -0
  58. package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
  59. package/dist/lib/components/ui/fields/index.d.ts +1 -0
  60. package/dist/lib/components/ui/fields/verification-code/describe-verification.d.ts +53 -0
  61. package/dist/lib/components/ui/fields/verification-code/index.d.ts +4 -0
  62. package/dist/lib/components/ui/fields/verification-code/partials/code-input.d.ts +12 -0
  63. package/dist/lib/components/ui/fields/verification-code/partials/code-message.d.ts +11 -0
  64. package/dist/lib/components/ui/fields/verification-code/partials/code-slots.d.ts +18 -0
  65. package/dist/lib/components/ui/fields/verification-code/partials/code-surface.d.ts +12 -0
  66. package/dist/lib/components/ui/fields/verification-code/partials/form-actions.d.ts +14 -0
  67. package/dist/lib/components/ui/fields/verification-code/partials/label-row.d.ts +10 -0
  68. package/dist/lib/components/ui/fields/verification-code/partials/locked-alert.d.ts +17 -0
  69. package/dist/lib/components/ui/fields/verification-code/partials/method-switch.d.ts +8 -0
  70. package/dist/lib/components/ui/fields/verification-code/partials/recovery-input.d.ts +7 -0
  71. package/dist/lib/components/ui/fields/verification-code/partials/resend-line.d.ts +10 -0
  72. package/dist/lib/components/ui/fields/verification-code/partials/status-line.d.ts +10 -0
  73. package/dist/lib/components/ui/fields/verification-code/throttle.d.ts +10 -0
  74. package/dist/lib/components/ui/fields/verification-code/types.d.ts +138 -0
  75. package/dist/lib/components/ui/fields/verification-code/use-answer-focus.d.ts +32 -0
  76. package/dist/lib/components/ui/fields/verification-code/use-code-entry.d.ts +43 -0
  77. package/dist/lib/components/ui/fields/verification-code/use-code-lock.d.ts +36 -0
  78. package/dist/lib/components/ui/fields/verification-code/use-code-resend.d.ts +29 -0
  79. package/dist/lib/components/ui/fields/verification-code/use-code-submit.d.ts +23 -0
  80. package/dist/lib/components/ui/fields/verification-code/use-entry-anchors.d.ts +6 -0
  81. package/dist/lib/components/ui/fields/verification-code/use-focus-on-switch.d.ts +7 -0
  82. package/dist/lib/components/ui/fields/verification-code/use-resend-focus.d.ts +20 -0
  83. package/dist/lib/components/ui/fields/verification-code/use-resend.d.ts +11 -0
  84. package/dist/lib/components/ui/fields/verification-code/use-short-reminder.d.ts +24 -0
  85. package/dist/lib/components/ui/fields/verification-code/use-stale-answer.d.ts +52 -0
  86. package/dist/lib/components/ui/fields/verification-code/use-throttle-focus.d.ts +16 -0
  87. package/dist/lib/components/ui/fields/verification-code/use-throttle.d.ts +10 -0
  88. package/dist/lib/components/ui/fields/verification-code/use-typed-value.d.ts +18 -0
  89. package/dist/lib/components/ui/fields/verification-code/use-verification-labels.d.ts +3 -0
  90. package/dist/lib/components/ui/fields/verification-code/verification-code.d.ts +11 -0
  91. package/dist/lib/components/ui/fields/verification-code/verification-lock-provider.d.ts +54 -0
  92. package/dist/lib/components/ui/layout/stepper/partials/header-nav.d.ts +10 -0
  93. package/dist/lib/components/ui/layout/stepper/partials/header-segments.d.ts +6 -0
  94. package/dist/lib/components/ui/layout/stepper/partials/header-summary.d.ts +12 -0
  95. package/dist/lib/components/ui/layout/stepper/partials/stepper-content.d.ts +8 -0
  96. package/dist/lib/components/ui/layout/stepper/partials/stepper-step-text.d.ts +13 -0
  97. package/dist/lib/components/ui/layout/stepper/stepper-connector.d.ts +6 -0
  98. package/dist/lib/components/ui/layout/stepper/stepper-header.d.ts +12 -0
  99. package/dist/lib/components/ui/layout/stepper/stepper-icon.d.ts +5 -0
  100. package/dist/lib/components/ui/layout/stepper/stepper-layout.d.ts +25 -0
  101. package/dist/lib/components/ui/layout/stepper/stepper-step.d.ts +9 -2
  102. package/dist/lib/components/ui/layout/stepper/stepper.d.ts +13 -3
  103. package/dist/lib/components/ui/overlays/dialog/dialog-parts.d.ts +8 -1
  104. package/dist/lib/i18n/resources/en/en.d.ts +59 -0
  105. package/dist/lib/i18n/resources/en/material.json.d.ts +61 -2
  106. package/dist/lib/i18n/resources/fr/fr.d.ts +59 -0
  107. package/dist/lib/i18n/resources/fr/material.json.d.ts +61 -2
  108. package/dist/lib/i18n/resources/resources.d.ts +118 -0
  109. package/dist/lib/i18n/translator.d.ts +1 -1
  110. package/dist/lib.js +1 -1
  111. package/dist/main.js +43 -43
  112. package/dist/map.js +4 -4
  113. package/dist/material.css +1 -1
  114. package/dist/pdf-reader.js +1 -1
  115. package/dist/print.js +2 -2
  116. package/dist/{public-DPPmNtZB.js → public-zVb_Nq_D.js} +6 -6
  117. package/dist/{rich-code-block-KQYR0qt3.js → rich-code-block-DMWZZJma.js} +4 -4
  118. package/dist/{sortable-provider-hPPTMtJA.js → sortable-provider-DstbgMVf.js} +1 -1
  119. package/dist/{spinner-Dd0os4cb.js → spinner-C4CgDEYm.js} +1 -1
  120. package/dist/{stored-language-Blyb68vN.js → stored-language-IaL1Ftn_.js} +122 -4
  121. package/dist/styles.css +8 -0
  122. package/dist/theme-picker.js +2 -2
  123. package/dist/{theme-toggle-BDRRkkiA.js → theme-toggle-CGW2_K54.js} +1 -1
  124. package/dist/{toolbar-items-D3hw7XZE.js → toolbar-items-CsLGJMEJ.js} +2 -2
  125. package/dist/{translate-material-CdJBbURx.js → translate-material-v9u-e7Kd.js} +2 -2
  126. package/dist/{translator-38JuN_VD.js → translator-Dk4_qE6U.js} +1 -1
  127. package/dist/{use-chat-composer-utGkZQ6X.js → use-chat-composer-Brcb5f7r.js} +12 -12
  128. package/dist/{use-heading-spy-bTccmEMF.js → use-heading-spy-DjKixjLm.js} +43 -31
  129. package/dist/{use-material-translation-DLsfkMxp.js → use-material-translation-DOkTaWK_.js} +2 -2
  130. package/docs/README.md +1 -0
  131. package/docs/components/README.md +1 -1
  132. package/docs/components/buttons-and-actions.md +2 -1
  133. package/docs/components/data-display.md +133 -4
  134. package/docs/components/feedback-and-status.md +113 -1
  135. package/docs/components/form-fields.md +163 -0
  136. package/docs/components/navigation-and-layout.md +66 -23
  137. package/docs/components/overlays-and-menus.md +3 -1
  138. package/docs/guides/i18n.md +4 -1
  139. package/docs/guides/ssr.md +3 -1
  140. package/docs/guides/two-factor.md +78 -0
  141. package/docs/previews/data-display-enrolmentcard.webp +0 -0
  142. package/docs/previews/data-display-recoverycodesstatus.webp +0 -0
  143. package/docs/previews/data-display-timeline.webp +0 -0
  144. package/docs/previews/feedback-status-stepupdialog.webp +0 -0
  145. package/docs/previews/form-fields-verificationcode.webp +0 -0
  146. package/docs/previews/navigation-layout-stepper.webp +0 -0
  147. package/docs/roadmap.md +30 -0
  148. package/lib/styles.css +8 -0
  149. package/package.json +2 -2
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The look the code field's two controls share, the six slots and the
3
+ * recovery code's text input: a tinted fill (`foreground` at 6%, 10% in dark)
4
+ * inside a hairline ring that holds 3:1 against the card in both themes
5
+ * (WCAG 1.4.11), a 2px primary ring over the page background while active,
6
+ * and a soft error tint. The ring is a transparent border in forced colours,
7
+ * where a box-shadow is dropped.
8
+ */
9
+ export declare const SURFACE = "border border-transparent bg-foreground/6 ring-1 ring-inset ring-foreground/50 transition-[box-shadow,background-color,color] duration-150 dark:bg-foreground/10 dark:ring-foreground/45 forced-colors:border-[ButtonText]";
10
+ export declare const SURFACE_ACTIVE = "bg-background ring-2 ring-primary-indicator dark:bg-background forced-colors:border-[Highlight]";
11
+ export declare const SURFACE_ERROR = "bg-error/10 text-error-text ring-error/75 dark:bg-error/20 dark:ring-error/90 forced-colors:border-[LinkText]";
12
+ export declare const SURFACE_LOCKED = "bg-foreground/4 text-muted-foreground ring-foreground/20 dark:bg-foreground/6 dark:ring-foreground/20 forced-colors:border-[GrayText]";
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { CodeEntryState } from '../use-code-entry.js';
3
+ type Props = Pick<CodeEntryState, 'labels' | 'busy' | 'locked' | 'alertId'> & {
4
+ submitLabel?: ReactNode;
5
+ secondaryAction?: ReactNode;
6
+ destructive?: boolean;
7
+ };
8
+ /**
9
+ * The inline buttons: `secondaryAction` and the submit button. Confirm stays
10
+ * enabled until the form is locked, so pressing it with too few digits can
11
+ * say "Enter all 6 digits."; a running check disables it through `loading`.
12
+ */
13
+ export declare function FormActions({ labels, busy, locked, alertId, submitLabel, secondaryAction, destructive, }: Props): import("react").JSX.Element;
14
+ export {};
@@ -0,0 +1,10 @@
1
+ type Props = {
2
+ htmlFor: string;
3
+ text: string;
4
+ locked: boolean;
5
+ /** The pill's text once locked. */
6
+ badge: string;
7
+ };
8
+ /** The field's label, with a "Locked" pill at the end once the form is locked. */
9
+ export declare function LabelRow({ htmlFor, text, locked, badge }: Props): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ import { CodeEntryState } from '../use-code-entry.js';
3
+ type Props = Pick<CodeEntryState, 'alertId' | 'alertRef' | 'lockedText' | 'ownLock'> & {
4
+ /** Replaces the lock icon; `null` shows none. */
5
+ icon?: ReactNode;
6
+ };
7
+ /**
8
+ * The locked state: a muted line with a lock icon, which the field and the
9
+ * submit button are described by. Only the one form that speaks the lock
10
+ * (`ownLock`: the first to show it, the form whose own answer locked it
11
+ * in the usual case) is an `alert`; the other forms under the same lock
12
+ * show the same text as a plain element, still described by, so a lock is
13
+ * announced once. Either takes the focus (`tabIndex={-1}`) after a submit
14
+ * that locked it, because the focused field has just become disabled.
15
+ */
16
+ export declare function LockedAlert({ alertId, alertRef, lockedText, ownLock, icon, }: Props): import("react").JSX.Element;
17
+ export {};
@@ -0,0 +1,8 @@
1
+ import { CodeEntryState } from '../use-code-entry.js';
2
+ type Props = Pick<CodeEntryState, 'recovery' | 'via' | 'labels' | 'busy' | 'locked' | 'submitting' | 'switchEntry'>;
3
+ /**
4
+ * "Use a recovery code" under the field, which becomes the way back ("Use my
5
+ * authenticator app", or "Use the code sent to you") once chosen.
6
+ */
7
+ export declare function MethodSwitch({ recovery, via, labels, busy, locked, submitting, switchEntry, }: Props): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ import { ComponentProps } from 'react';
2
+ type Props = {
3
+ state: 'idle' | 'error' | 'locked';
4
+ } & Omit<ComponentProps<'input'>, 'type'>;
5
+ /** The recovery code's text input, with the slots' tinted fill and ring. */
6
+ export declare function RecoveryInput({ state, className, ...props }: Props): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,10 @@
1
+ import { CodeEntryState } from '../use-code-entry.js';
2
+ type Props = Pick<CodeEntryState, 'resendLabel' | 'busy' | 'locked' | 'resend' | 'resendWaiting' | 'messageId'>;
3
+ /**
4
+ * "Resend the code" alone on its own line under the field, which becomes "New
5
+ * code" (or "Try again" for an app's code) once the code expired. While a
6
+ * throttled answer's wait lasts it is disabled and described by the message
7
+ * under the field, which says why.
8
+ */
9
+ export declare function ResendLine({ resendLabel, busy, locked, resend, resendWaiting, messageId, }: Props): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,10 @@
1
+ import { ReactNode } from 'react';
2
+ type Props = {
3
+ /** The host's notice line. */
4
+ status?: ReactNode;
5
+ /** Shown, not read (the live region reads it), once a new code was sent. */
6
+ resentText?: ReactNode;
7
+ };
8
+ /** The notice line over the field and the "new code sent" line under it. */
9
+ export declare function StatusLine({ status, resentText }: Props): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,10 @@
1
+ import { VerificationCodeLabels, VerificationError } from './types.js';
2
+ /** The wait a throttled answer names, in seconds; none when it is not throttled or names no usable wait. */
3
+ export declare function throttleSeconds(error: VerificationError, retryAfter: number | undefined): number | undefined;
4
+ /**
5
+ * What a throttled answer says: the wait in minutes rounded up, in seconds
6
+ * under a minute, or a general line when `retryAfter` is not given. An
7
+ * authenticator or recovery code (`mailed` false) is not "asked for again", so
8
+ * its wait reads "before trying again".
9
+ */
10
+ export declare function throttledText(labels: Pick<VerificationCodeLabels, 'throttled' | 'throttledMinutes' | 'throttledSeconds' | 'throttledMinutesApp' | 'throttledSecondsApp'>, retryAfter: number | undefined, mailed?: boolean): string;
@@ -0,0 +1,138 @@
1
+ import { ComponentProps, ReactNode } from 'react';
2
+ /** Every built-in string of {@link VerificationCode}, each overridable. */
3
+ export type VerificationCodeLabels = {
4
+ /** Names the code field. "Code". */
5
+ label: string;
6
+ /** Names the field once "Use a recovery code" was chosen. "Recovery code". */
7
+ recoveryLabel: string;
8
+ /** Switches to the recovery code. "Use a recovery code". */
9
+ useRecovery: string;
10
+ /** Switches back to an authenticator app's code. "Use my authenticator app". */
11
+ useApp: string;
12
+ /** Switches back to the code that was sent. "Use the code sent to you". */
13
+ useEmail: string;
14
+ /** The submit button. "Confirm". */
15
+ confirm: string;
16
+ /** The line under the field that asks for another code. "Resend the code". */
17
+ resend: string;
18
+ /** Said once another code was sent. "A new code was sent." */
19
+ resent: string;
20
+ /** Said while another code is being sent. "Sending a new code…" */
21
+ sending: string;
22
+ /** Replaces "Resend the code" once an e-mailed code expired. "New code". */
23
+ newCode: string;
24
+ /** Replaces it once an app's code expired. "Try again". */
25
+ tryAgain: string;
26
+ /** The start of the message for a wrong code. "Wrong code." */
27
+ wrong: string;
28
+ /** Added to it when the count is known; an ICU message of `{count}`. */
29
+ triesLeft: (count: number) => string;
30
+ /** Said under the field when Confirm is pressed with fewer digits than it has slots; `count` is the slots. "Enter all 6 digits." */
31
+ incomplete: (count: number) => string;
32
+ /** The same for an empty recovery code. "Enter your recovery code." */
33
+ incompleteRecovery: string;
34
+ /** An expired code, when the host sent no message. */
35
+ expired: string;
36
+ /** A check that could not be made, when the host sent no message. */
37
+ failed: string;
38
+ /** The locked alert, when the host sent no message. */
39
+ locked: string;
40
+ /** A throttled answer with no `retryAfter`. "Too many requests. Wait a moment and try again." */
41
+ throttled: string;
42
+ /** A throttled answer of a minute or more; an ICU message of `{n}` (rounded up). "Wait {n} min before asking for a new code." */
43
+ throttledMinutes: (n: number) => string;
44
+ /** A throttled answer under a minute; an ICU message of `{n}`. "Wait {n} s before asking for a new code." */
45
+ throttledSeconds: (n: number) => string;
46
+ /** Like `throttledMinutes`, for an authenticator or recovery code. "Wait {n} min before trying again." */
47
+ throttledMinutesApp: (n: number) => string;
48
+ /** Like `throttledSeconds`, for an authenticator or recovery code. "Wait {n} s before trying again." */
49
+ throttledSecondsApp: (n: number) => string;
50
+ /** The pill beside the label once the form is locked. "Locked". */
51
+ lockedBadge: string;
52
+ };
53
+ /** Icons the host replaces; the locked alert's own icon by default. */
54
+ export type VerificationCodeIcons = {
55
+ /** The locked alert's icon; `null` shows none. */
56
+ locked?: ReactNode;
57
+ };
58
+ /**
59
+ * What the code was issued as: `'email'` is a code sent to the person,
60
+ * `'secondFactor'` one from an authenticator app (a recovery code may stand
61
+ * in for it). The strings are the ones a session's answer already carries.
62
+ */
63
+ export type VerificationVia = 'email' | 'secondFactor';
64
+ /** What was typed: the issued code (from an app or an e-mail), or a recovery code. */
65
+ export type VerificationKind = 'code' | 'recovery';
66
+ /**
67
+ * Why the last code was not taken: `'invalid'` (wrong, with the tries left
68
+ * when `attemptsLeft` is given), `'expired'` (spent or out of date),
69
+ * `'failed'` (the check could not be made), `'throttled'` (too many
70
+ * requests for a new code: nothing was held against the code, see
71
+ * `retryAfter`), or your own words as a node, shown as a wrong code's message.
72
+ */
73
+ export type VerificationError = 'invalid' | 'expired' | 'failed' | 'throttled' | ReactNode;
74
+ export type VerificationCodeProps = Omit<ComponentProps<'form'>, 'onSubmit' | 'children' | 'id'> & {
75
+ /** How the code was issued. */
76
+ via: VerificationVia;
77
+ /**
78
+ * Tries left, once known. At `0` an e-mailed code reads as expired (ask
79
+ * for a new one), and an app or recovery code locks the form and writes
80
+ * the page-wide lock, since a lock holds for the whole account.
81
+ */
82
+ attemptsLeft?: number;
83
+ /** Locks the form and the page-wide lock, for an app or recovery code; ignored for an e-mailed code. */
84
+ locked?: boolean;
85
+ /** The last refusal; leave it out once a new code is being typed or accepted. */
86
+ error?: VerificationError;
87
+ /**
88
+ * Seconds to wait before asking for a new code, with `error="throttled"`.
89
+ * "Resend" is disabled until it elapses (counted from when the answer
90
+ * arrived) and the message names the wait, in minutes rounded up (seconds
91
+ * under a minute). Left out, the message is general and "Resend" stays on.
92
+ * A throttle never locks the form and never counts as a refused code (an app or recovery code that is `locked` or has `attemptsLeft: 0` stays locked).
93
+ */
94
+ retryAfter?: number;
95
+ /** A request is in flight: the field and buttons are disabled, Confirm shows it. */
96
+ pending?: boolean;
97
+ /**
98
+ * Called with the code and what it is. Return a promise to hold a second
99
+ * submit. A rejection is swallowed, not rethrown: map a failure to
100
+ * `error="failed"`.
101
+ */
102
+ onSubmit: (code: string, options: {
103
+ kind: VerificationKind;
104
+ }) => unknown;
105
+ /**
106
+ * Asks for another code: "Resend the code" for an e-mailed code, and "New
107
+ * code" (e-mail) or "Try again" (app) once a code expired.
108
+ */
109
+ onResend?: () => unknown;
110
+ /** A new code was sent: says so, in the line under the field and to a screen reader. */
111
+ resent?: boolean;
112
+ /**
113
+ * Offers "Use a recovery code", which swaps the field for a text field (40
114
+ * characters, trimmed) and back. On for `secondFactor`.
115
+ */
116
+ allowRecovery?: boolean;
117
+ /** Slots in the code field. 6 by default. */
118
+ length?: number;
119
+ /** The form's id; the field, the alert and the status line take theirs from it. */
120
+ id?: string;
121
+ /** The button's text. "Confirm". */
122
+ submitLabel?: ReactNode;
123
+ /**
124
+ * `'inline'` (default) draws the submit button and `secondaryAction`;
125
+ * `'none'` leaves them to the host, whose buttons point at the form with
126
+ * `form={id}`.
127
+ */
128
+ actions?: 'inline' | 'none';
129
+ /** Beside the submit button (Cancel, say); it stays usable when locked. */
130
+ secondaryAction?: ReactNode;
131
+ /** A destructive action (turning protection off): the button is red. */
132
+ destructive?: boolean;
133
+ /** A notice line over the field, such as "Your session is confirmed". */
134
+ status?: ReactNode;
135
+ labels?: Partial<VerificationCodeLabels>;
136
+ icons?: VerificationCodeIcons;
137
+ autoFocus?: boolean;
138
+ };
@@ -0,0 +1,32 @@
1
+ import { RefObject } from 'react';
2
+ import { VerificationPhase } from './describe-verification.js';
3
+ type Input = {
4
+ phase: VerificationPhase;
5
+ pending: boolean;
6
+ /** The host's answer; a change of either is a new answer. */
7
+ attemptsLeft: number | undefined;
8
+ error: unknown;
9
+ fieldRef: RefObject<HTMLElement | null>;
10
+ alertRef: RefObject<HTMLElement | null>;
11
+ clear: () => void;
12
+ };
13
+ /**
14
+ * After an answer to a code of this form: a wrong or expired code leaves the
15
+ * field empty and focused, a failed one keeps its code and focuses the field,
16
+ * a lock moves the focus to its alert (the focused field just became
17
+ * disabled). A lock another form wrote moves nothing. `arm()` is called on
18
+ * submit; the step runs once the submit settled and `pending` is down, so a
19
+ * second identical refusal is answered too.
20
+ *
21
+ * `quiet` is true for an answer that sends the focus to the field (described
22
+ * by the message) or to the alert: a screen reader reads it there, so the
23
+ * live region leaves it out and it is not spoken twice. Answers that move no
24
+ * focus (a new code sent, a host-set error with no submit) stay in the live
25
+ * region.
26
+ */
27
+ export declare function useAnswerFocus({ phase, pending, attemptsLeft, error, fieldRef, alertRef, clear, }: Input): {
28
+ arm: () => void;
29
+ settle: () => void;
30
+ quiet: boolean;
31
+ };
32
+ export {};
@@ -0,0 +1,43 @@
1
+ import { ReactNode } from 'react';
2
+ import { VerificationCodeProps } from './types.js';
3
+ type Props = Pick<VerificationCodeProps, 'via' | 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'pending' | 'onSubmit' | 'onResend' | 'resent' | 'allowRecovery' | 'length' | 'labels' | 'id'>;
4
+ /**
5
+ * What a code form keeps itself, and nothing else: the typed value, the
6
+ * app or recovery switch, the focus after an answer, and the submit guard.
7
+ * The words and the lock come from {@link describeVerification}. A rejected
8
+ * `onSubmit` is swallowed: the host maps a failure to `error="failed"`.
9
+ */
10
+ export declare function useCodeEntry(props: Props): {
11
+ /** A submit is in flight: the entry stays until its answer is in. */
12
+ submitting: boolean;
13
+ switchEntry: () => void;
14
+ fieldRef: import('react').RefObject<HTMLDivElement | null>;
15
+ alertRef: import('react').RefObject<HTMLDivElement | null>;
16
+ onSubmit: (event: import('react').FormEvent) => void;
17
+ resend: () => void;
18
+ showResend: boolean;
19
+ resendLabel: string;
20
+ resendWaiting: boolean;
21
+ id: string;
22
+ via: import('./types.js').VerificationVia;
23
+ labels: import('./types.js').VerificationCodeLabels;
24
+ phase: import('./describe-verification.js').VerificationPhase;
25
+ busy: boolean;
26
+ recovery: boolean;
27
+ allowRecovery: boolean;
28
+ length: number;
29
+ value: string;
30
+ setValue: import('react').Dispatch<import('react').SetStateAction<string>>;
31
+ canSubmit: boolean;
32
+ locked: boolean;
33
+ alertId: string;
34
+ lockedText: string | number | bigint | boolean | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined>;
35
+ ownLock: boolean;
36
+ shortage: boolean;
37
+ message: ReactNode;
38
+ announcement: ReactNode;
39
+ resent: boolean;
40
+ messageId: string;
41
+ };
42
+ export type CodeEntryState = ReturnType<typeof useCodeEntry>;
43
+ export {};
@@ -0,0 +1,36 @@
1
+ import { VerificationCodeLabels, VerificationCodeProps } from './types.js';
2
+ type Input = Pick<VerificationCodeProps, 'via' | 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'resent'> & {
3
+ pending: boolean;
4
+ labels: VerificationCodeLabels;
5
+ /** A recovery code is being typed. */
6
+ recovery: boolean;
7
+ };
8
+ /**
9
+ * What a form shows for the answer it was given, and its part in the
10
+ * page-wide lock: it writes the lock when its own answer locks it, is held
11
+ * by the lock otherwise, and says whether it is the lock's one alert.
12
+ */
13
+ export declare function useCodeLock({ labels, recovery, pending, ...given }: Input): {
14
+ view: {
15
+ phase: import('./describe-verification.js').VerificationPhase;
16
+ message: import('react').ReactNode;
17
+ expired: boolean;
18
+ writesLock: boolean;
19
+ lockedText: string | number | bigint | boolean | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<import('react').ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<import('react').ReactNode> | null | undefined>;
20
+ announcement: import('react').ReactNode;
21
+ };
22
+ stale: {
23
+ answer: import('./use-stale-answer.js').HostAnswer;
24
+ submitting: boolean;
25
+ markStale: () => void;
26
+ wrap: <A extends unknown[]>(run: (...args: A) => unknown) => (...args: A) => Promise<unknown>;
27
+ };
28
+ /** The answer the phase was read from (masked after an entry switch). */
29
+ answer: {
30
+ attemptsLeft: number | undefined;
31
+ error: import('./types.js').VerificationError;
32
+ };
33
+ /** This form is the lock's one alert (the first to show it): the others in scope only show the text. */
34
+ ownLock: boolean;
35
+ };
36
+ export {};
@@ -0,0 +1,29 @@
1
+ import { RefObject } from 'react';
2
+ import { VerificationPhase } from './describe-verification.js';
3
+ import { VerificationCodeLabels, VerificationCodeProps } from './types.js';
4
+ type Input = Pick<VerificationCodeProps, 'via' | 'error' | 'retryAfter' | 'onResend'> & {
5
+ phase: VerificationPhase;
6
+ /** The form is the expired one (see `describeVerification`). */
7
+ expired: boolean;
8
+ recovery: boolean;
9
+ labels: VerificationCodeLabels;
10
+ fieldRef: RefObject<HTMLElement | null>;
11
+ };
12
+ /**
13
+ * "Resend the code": whether it is offered, what it says, and whether it
14
+ * waits for a throttled answer's `retryAfter` (one timer, no live countdown).
15
+ * Without `retryAfter` a throttled answer leaves it enabled.
16
+ */
17
+ export declare function useCodeResend({ via, error, retryAfter, onResend, phase, expired, recovery, labels, fieldRef, }: Input): {
18
+ resending: boolean;
19
+ /** The focus went to the field, which reads the message: the live region stays quiet. */
20
+ quiet: boolean;
21
+ /** What the form's parts read. */
22
+ view: {
23
+ resend: () => void;
24
+ showResend: boolean;
25
+ resendLabel: string;
26
+ resendWaiting: boolean;
27
+ };
28
+ };
29
+ export {};
@@ -0,0 +1,23 @@
1
+ import { FormEvent } from 'react';
2
+ import { VerificationCodeProps } from './types.js';
3
+ import { useAnswerFocus } from './use-answer-focus.js';
4
+ import { useShortReminder } from './use-short-reminder.js';
5
+ import { useTypedValue } from './use-typed-value.js';
6
+ type Input = {
7
+ onSubmit: VerificationCodeProps['onSubmit'];
8
+ typed: ReturnType<typeof useTypedValue>;
9
+ focus: ReturnType<typeof useAnswerFocus>;
10
+ short: ReturnType<typeof useShortReminder>;
11
+ pending: boolean;
12
+ locked: boolean;
13
+ };
14
+ /**
15
+ * The form's submit: one in flight at a time, the answer's focus armed first,
16
+ * and the reminder instead when the code is incomplete. A rejection of the
17
+ * host's `onSubmit` is swallowed: the host maps it to `error="failed"`.
18
+ */
19
+ export declare function useCodeSubmit({ onSubmit, typed, focus, short, pending, locked, }: Input): {
20
+ canSubmit: boolean;
21
+ onSubmit: (event: FormEvent) => void;
22
+ };
23
+ export {};
@@ -0,0 +1,6 @@
1
+ /** The form's id (the host's, or a generated one) and the refs the focus steps use: the code field and the lock's alert. */
2
+ export declare function useEntryAnchors(given: string | undefined): {
3
+ id: string;
4
+ fieldRef: import('react').RefObject<HTMLDivElement | null>;
5
+ alertRef: import('react').RefObject<HTMLDivElement | null>;
6
+ };
@@ -0,0 +1,7 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Switching to the other field (code or recovery) moves the focus to it, but
4
+ * not on mount, and only when the focus was inside the form or fell to the
5
+ * page: a host that changes `via` from a button of its own keeps its focus.
6
+ */
7
+ export declare function useFocusOnSwitch(recovery: boolean, fieldRef: RefObject<HTMLElement | null>): void;
@@ -0,0 +1,20 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Whether "Resend" held the focus, followed on `focusin` / `focusout` (the
4
+ * record outlives the button, which may be removed or disabled before an
5
+ * effect runs). Only the resend line inside this form's root counts. A button
6
+ * that is disabled while it holds the focus keeps the record (the browser,
7
+ * not the user, takes the focus off it), until the focus is seen going
8
+ * elsewhere: a `focusin` on anything else, or a `focusout` whose
9
+ * `relatedTarget` is an element outside this resend line.
10
+ */
11
+ export declare function useResendHeld(fieldRef: RefObject<HTMLElement | null>): RefObject<boolean>;
12
+ /**
13
+ * When "Resend" / "Try again" goes away while it has the focus (the host
14
+ * answered `resent`, or cleared `error`), the focus would fall to the page.
15
+ * It goes to the code field instead. The button is gone by the time an effect
16
+ * runs, so the focus is followed as it moves: a button that left the page
17
+ * while it held it is the case. Only the resend line inside this form's root
18
+ * counts, so another form on the page never pulls the focus.
19
+ */
20
+ export declare function useResendFocus(shown: boolean, fieldRef: RefObject<HTMLElement | null>): void;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * "Resend the code": true while the host's `onResend` has not settled, and `settled`
3
+ * counts the ones that did (a throttled wait restarts on it). A
4
+ * rejection, or a throw before it returns a promise, ends the wait and is
5
+ * swallowed: the host maps a failure to its own props.
6
+ */
7
+ export declare function useResend(onResend: (() => unknown) | undefined): {
8
+ resending: boolean;
9
+ settled: number;
10
+ resend: () => void;
11
+ };
@@ -0,0 +1,24 @@
1
+ import { RefObject } from 'react';
2
+ import { VerificationCodeLabels } from './types.js';
3
+ type Input = {
4
+ /** The typed value and the entry: typing or switching takes the reminder away. */
5
+ value: string;
6
+ recovery: boolean;
7
+ length: number;
8
+ labels: VerificationCodeLabels;
9
+ fieldRef: RefObject<HTMLElement | null>;
10
+ };
11
+ /**
12
+ * "Enter all 6 digits.": the reminder under the field when Confirm (or Enter)
13
+ * is pressed with fewer digits than slots. `show()` focuses the field and
14
+ * remembers whether that moved the focus: when it did, the field's own
15
+ * description is read there and the live region stays quiet; when the focus
16
+ * was already in the field nothing would be read, so the live region says it.
17
+ */
18
+ export declare function useShortReminder({ value, recovery, length, labels, fieldRef, }: Input): {
19
+ text: string | undefined;
20
+ /** Whether the live region should say it. */
21
+ announce: boolean;
22
+ show: () => void;
23
+ };
24
+ export {};
@@ -0,0 +1,52 @@
1
+ import { VerificationCodeProps } from './types.js';
2
+ export type HostAnswer = Pick<VerificationCodeProps, 'attemptsLeft' | 'locked' | 'error'>;
3
+ /**
4
+ * What was on screen when the entry was switched, how many submits had
5
+ * started, whether one was still in flight, and which entry (`recovery`: the
6
+ * recovery code, else the app or e-mailed code) the answer belonged to.
7
+ */
8
+ export type StaleMark = {
9
+ answer: HostAnswer;
10
+ started: number;
11
+ inflight: boolean;
12
+ recovery: boolean;
13
+ };
14
+ type Progress = {
15
+ started: number;
16
+ done: number;
17
+ pending: boolean;
18
+ };
19
+ /**
20
+ * Whether `current` is still the answer that was on screen when the entry
21
+ * was switched: the same tries, lock flag and error (by identity).
22
+ */
23
+ export declare function isStaleAnswer(stale: HostAnswer | null, current: HostAnswer): boolean;
24
+ /**
25
+ * The answer the form reads. What the host said before the entry was switched
26
+ * answered the other kind of code, so it holds nothing against the new entry
27
+ * until the host answers again: a changed answer, or a submit made since the
28
+ * switch that has ended (and whose `pending` is down). It is shown again when
29
+ * the entry it belonged to comes back. A submit that was still in flight at
30
+ * the switch answers the other entry, so only a submit made since the switch
31
+ * lets an answer through. A `'throttled'` answer
32
+ * is about asking for a new code, so it is never masked and never counts as
33
+ * the answer that was on screen. Pure, so the focus
34
+ * step and the phase see the same answer in the same render.
35
+ */
36
+ export declare function maskAnswer(mark: StaleMark | null, current: HostAnswer, { started, done, pending }: Progress, recovery: boolean): HostAnswer;
37
+ /**
38
+ * Masks the host's answer after an entry switch (see {@link maskAnswer}). A
39
+ * lock that was already written stays written: the store never unlocks. The
40
+ * host should raise `pending` in the same tick as its `onSubmit`, or return
41
+ * the answer's promise.
42
+ */
43
+ export declare function useStaleAnswer(answer: HostAnswer, pending: boolean, recovery: boolean): {
44
+ answer: HostAnswer;
45
+ /** A submit has started and not ended: the entry stays as it is until the answer is in. */
46
+ submitting: boolean;
47
+ /** Call when the entry is switched. */
48
+ markStale: () => void;
49
+ /** Wraps the host's `onSubmit`: the next answer is a fresh one. */
50
+ wrap: <A extends unknown[]>(run: (...args: A) => unknown) => (...args: A) => Promise<unknown>;
51
+ };
52
+ export {};
@@ -0,0 +1,16 @@
1
+ import { RefObject } from 'react';
2
+ import { VerificationPhase } from './describe-verification.js';
3
+ /**
4
+ * A throttled answer disables "Resend", which would drop the focus it had
5
+ * (the press that was refused). Whether it had it is the record of
6
+ * `useResendHeld`, not `document.activeElement`: this runs in a passive effect
7
+ * after the commit that disabled the button, when the focus may already be on
8
+ * the page. The focus goes to the code field instead,
9
+ * which is described by the message, so `quiet` is true and the live region
10
+ * does not say the same words a second time (this runs as the answer arrives,
11
+ * as the press that was refused is still being answered): the same rule as a refused code.
12
+ * It stays true until the answer is gone, so the end of the wait says nothing.
13
+ */
14
+ export declare function useThrottleFocus(phase: VerificationPhase, willWait: boolean, fieldRef: RefObject<HTMLElement | null>,
15
+ /** The count of settled resends: the same answer again moves the focus again. */
16
+ settled?: number): boolean;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Whether "Resend" must wait: true from when a throttled answer with a wait
3
+ * arrived until that wait elapsed. One timer, one state change at the end, no
4
+ * tick per second. It starts in an effect, so the server and the first client
5
+ * render agree (not waiting) and no timer runs on the server. A new
6
+ * answer is a change of `seconds` (or the error going away and coming back),
7
+ * and so is a resend that settled while the answer is still throttled, even
8
+ * with the same `retryAfter`: `restart` is the count of settled resends.
9
+ */
10
+ export declare function useThrottle(seconds: number | undefined, restart?: number): boolean;
@@ -0,0 +1,18 @@
1
+ import { VerificationVia } from './types.js';
2
+ /**
3
+ * The typed value and the app or recovery switch of a code form. The switch
4
+ * goes back to the code when `via` changes or the recovery code is no longer
5
+ * offered: the person is never left in an entry that has no way back.
6
+ */
7
+ export declare function useTypedValue(length: number, via: VerificationVia, allowRecovery: boolean): {
8
+ value: string;
9
+ setValue: import('react').Dispatch<import('react').SetStateAction<string>>;
10
+ recovery: boolean;
11
+ complete: boolean;
12
+ /** What `onSubmit` receives, and which kind it is. */
13
+ payload: () => {
14
+ code: string;
15
+ kind: "code" | "recovery";
16
+ };
17
+ switchEntry: () => void;
18
+ };
@@ -0,0 +1,3 @@
1
+ import { VerificationCodeLabels } from './types.js';
2
+ /** The built-in labels (English or the active language), with their overrides. */
3
+ export declare function useVerificationLabels(overrides?: Partial<VerificationCodeLabels>): VerificationCodeLabels;
@@ -0,0 +1,11 @@
1
+ import { VerificationCodeProps } from './types.js';
2
+ /**
3
+ * A form for a one-time code, presentational and controlled: it keeps the
4
+ * typed value, the app or recovery switch, the focus and the submit guard,
5
+ * and shows the answer it is given (`error`, `retryAfter`, `attemptsLeft`,
6
+ * `locked`, `pending`, `resent`). It fetches nothing and holds no state machine:
7
+ * `onSubmit` and `onResend` are the app's. With no tries left an e-mailed code
8
+ * reads as expired, and an app or recovery code locks the form and the
9
+ * page-wide lock of its `VerificationLockProvider`.
10
+ */
11
+ export declare function VerificationCode({ via, attemptsLeft, locked: lockedProp, error, retryAfter, pending, onSubmit, onResend, resent, allowRecovery, length, labels: labelOverrides, id, submitLabel, actions, secondaryAction, destructive, status, icons, autoFocus, className, ...props }: VerificationCodeProps): import("react").JSX.Element;