@nxgt/material 3.49.0 → 3.51.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 (99) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +1 -1
  3. package/dist/{async-slice-DlvKCKAa.js → async-slice-BGtmF3K5.js} +2 -2
  4. package/dist/{button-DJgaQbBD.js → button-BWcr2b49.js} +45 -76
  5. package/dist/charts.js +3 -3
  6. package/dist/{chip-DN44R1vW.js → chip-CmLW6ZrT.js} +3 -3
  7. package/dist/{code-editor-BJ9ewxSC.js → code-editor-BKMaeIF6.js} +6 -6
  8. package/dist/code-editor.js +5 -5
  9. package/dist/{code-language-items-BJE3VuQg.js → code-language-items-Cs1Pwd1h.js} +2 -2
  10. package/dist/components/ui/layout/app-shell/activity-backdrop-shapes.css +14 -9
  11. package/dist/components/ui/layout/auth-card/auth-card-backdrop.css +2 -2
  12. package/dist/{components-AtBccCir.js → components-CuwU9Sux.js} +11878 -11614
  13. package/dist/components.js +26 -27
  14. package/dist/{dialog-ODql4vH7.js → dialog-TdT_5iUc.js} +7 -7
  15. package/dist/dnd.js +1 -1
  16. package/dist/{dropdown-menu-DRXYP9ta.js → dropdown-menu-BozV6Ikw.js} +25 -26
  17. package/dist/editor.js +9 -9
  18. package/dist/{empty-state-C9QqvBU1.js → empty-state-gzBPimAo.js} +2 -2
  19. package/dist/{escape-owner-DCrlERLM.js → escape-owner-Bu-aDEEO.js} +1 -1
  20. package/dist/{field-blur-DYGyIdfD.js → field-blur-47zmuDkH.js} +1 -1
  21. package/dist/{field-blur-context-B-fSpl1H.js → field-blur-context-6McYOnM8.js} +1 -1
  22. package/dist/hooks.js +2 -2
  23. package/dist/{hover-card-EO_CckIx.js → hover-card-zHdZJpBG.js} +14 -14
  24. package/dist/{i18n-provider-C0fB0sEL.js → i18n-provider-Ang2f31m.js} +1 -1
  25. package/dist/i18n.js +5 -5
  26. package/dist/{icon-badge-BQYj_LE6.js → icon-badge-CRFGIQPX.js} +3 -3
  27. package/dist/{icon-button-B481L2TP.js → icon-button-CtG3Snfm.js} +119 -87
  28. package/dist/lib/components/ui/actions/icon-button/icon-button-busy.d.ts +22 -0
  29. package/dist/lib/components/ui/actions/icon-button/icon-button-shape.d.ts +2 -0
  30. package/dist/lib/components/ui/actions/icon-button/icon-button.d.ts +7 -0
  31. package/dist/lib/components/ui/collections/data-table/data-table-selection-host.d.ts +7 -0
  32. package/dist/lib/components/ui/collections/data-table/internal.d.ts +1 -0
  33. package/dist/lib/components/ui/collections/data-table/partials/layouts/data-table-list-bar.d.ts +2 -1
  34. package/dist/lib/components/ui/collections/filter/bar/partials/filter-quick-toggle.d.ts +3 -2
  35. package/dist/lib/components/ui/collections/filter/sections/filter-sections-classes.d.ts +7 -1
  36. package/dist/lib/components/ui/collections/page-footer/page-footer.d.ts +6 -1
  37. package/dist/lib/components/ui/collections/row-menu/row-menu-trigger.d.ts +5 -2
  38. package/dist/lib/components/ui/collections/server-table/index.d.ts +1 -1
  39. package/dist/lib/components/ui/collections/server-table/partials/filtered-server-table.d.ts +8 -0
  40. package/dist/lib/components/ui/collections/server-table/partials/server-table-band.d.ts +10 -1
  41. package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk-buttons.d.ts +3 -2
  42. package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk-more.d.ts +4 -2
  43. package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk.d.ts +2 -1
  44. package/dist/lib/components/ui/collections/server-table/partials/server-table-controls.d.ts +16 -0
  45. package/dist/lib/components/ui/collections/server-table/partials/server-table-empty-chips.d.ts +5 -3
  46. package/dist/lib/components/ui/collections/server-table/partials/server-table-grid.d.ts +3 -1
  47. package/dist/lib/components/ui/collections/server-table/partials/server-table-selection-bar.d.ts +17 -0
  48. package/dist/lib/components/ui/collections/server-table/partials/server-table-view.d.ts +15 -0
  49. package/dist/lib/components/ui/collections/server-table/partials/use-server-table-phone-row.d.ts +14 -0
  50. package/dist/lib/components/ui/collections/server-table/partials/use-server-table-selection-slots.d.ts +24 -0
  51. package/dist/lib/components/ui/collections/server-table/types-paging.d.ts +17 -0
  52. package/dist/lib/components/ui/collections/server-table/types.d.ts +3 -10
  53. package/dist/lib/components/ui/collections/server-table/use-selection-band.d.ts +14 -0
  54. package/dist/lib/components/ui/feedback/step-up-dialog/partials/step-up-body.d.ts +5 -3
  55. package/dist/lib/components/ui/feedback/step-up-dialog/partials/step-up-request-error.d.ts +15 -0
  56. package/dist/lib/components/ui/feedback/step-up-dialog/step-up-dialog.d.ts +6 -3
  57. package/dist/lib/components/ui/feedback/step-up-dialog/types.d.ts +12 -1
  58. package/dist/lib/components/ui/feedback/step-up-dialog/use-retry-focus.d.ts +27 -0
  59. package/dist/lib/components/ui/feedback/step-up-dialog/use-retry.d.ts +11 -0
  60. package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
  61. package/dist/lib/components/ui/fields/verification-code/use-settled-focus.d.ts +10 -0
  62. package/dist/lib/components/ui/layout/app-shell/use-keep-shapes-inside.d.ts +12 -1
  63. package/dist/lib/i18n/resources/en/en.d.ts +4 -0
  64. package/dist/lib/i18n/resources/en/material.json.d.ts +6 -2
  65. package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
  66. package/dist/lib/i18n/resources/fr/material.json.d.ts +6 -2
  67. package/dist/lib/i18n/resources/resources.d.ts +8 -0
  68. package/dist/lib/i18n/translator.d.ts +1 -1
  69. package/dist/lib.js +1 -1
  70. package/dist/main.js +43 -44
  71. package/dist/map.js +8 -8
  72. package/dist/material.css +1 -1
  73. package/dist/pdf-reader.js +1 -1
  74. package/dist/print.js +2 -2
  75. package/dist/{public-CZBz4JVu.js → public-CTZ5RK_Y.js} +20 -20
  76. package/dist/{rich-code-block-597e0_Qm.js → rich-code-block-oTgL-s4W.js} +5 -5
  77. package/dist/{sortable-provider-CK_xAk2H.js → sortable-provider-CpA5NYgD.js} +2 -2
  78. package/dist/{dist-B61_o9Mg.js → spinner-UvqlDsV8.js} +478 -256
  79. package/dist/{stored-language-IaL1Ftn_.js → stored-language-Cb9FMEwk.js} +12 -4
  80. package/dist/theme-picker.js +2 -2
  81. package/dist/{theme-toggle-Dnjn83TJ.js → theme-toggle-BZVz6O5q.js} +1 -1
  82. package/dist/{toolbar-items-CCwIu7fE.js → toolbar-items-C09bJphe.js} +106 -106
  83. package/dist/{translate-material-v9u-e7Kd.js → translate-material-D6KCK21i.js} +2 -2
  84. package/dist/{translator-Dk4_qE6U.js → translator-BnQXtpSZ.js} +1 -1
  85. package/dist/{use-chat-composer-Ot5XUbdn.js → use-chat-composer-AZAj4tFJ.js} +4881 -4882
  86. package/dist/{button-tones-BwuVvAmd.js → use-click-lock-BZYtTmVt.js} +37 -7
  87. package/dist/{use-heading-spy-DjKixjLm.js → use-heading-spy-C9-A2md2.js} +1 -1
  88. package/dist/{use-material-translation-DOkTaWK_.js → use-material-translation-pLgSqqLw.js} +2 -2
  89. package/docs/components/buttons-and-actions.md +2 -1
  90. package/docs/components/data-table-filter-and-lists.md +67 -14
  91. package/docs/components/feedback-and-status.md +22 -3
  92. package/docs/components/form-fields.md +7 -0
  93. package/docs/guides/backgrounds.md +3 -1
  94. package/docs/guides/cards-and-tiles.md +3 -0
  95. package/docs/guides/server-lists-url.md +3 -2
  96. package/lib/components/ui/layout/app-shell/activity-backdrop-shapes.css +14 -9
  97. package/lib/components/ui/layout/auth-card/auth-card-backdrop.css +2 -2
  98. package/package.json +1 -1
  99. package/dist/spinner-BhuZuHK1.js +0 -229
@@ -6,7 +6,8 @@ import { useServerTable } from '../use-server-table.js';
6
6
  export declare function ServerTableBulk<T extends RowData>({ props, state, phone, tableRoot, }: {
7
7
  props: ServerTableProps<T>;
8
8
  state: ReturnType<typeof useServerTable<T>>;
9
- phone?: boolean;
9
+ /** A number: how many buttons stay on a phone's bar (default 3). */
10
+ phone?: boolean | number;
10
11
  /** The stable outer `data-slot="server-table"` element: it outlives the
11
12
  * table/cards/tiles view swap that makes `state.table` transiently null. */
12
13
  tableRoot: () => HTMLElement | null;
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * The band's controls zone when `bulkActions` has the Filter's bar to
4
+ * replace (#1718): the search landmark and the selection bar share one grid
5
+ * cell. While rows are selected the landmark stays mounted (its search text
6
+ * and focus handling intact) but is `invisible` and `inert`, and keeps its
7
+ * size, so the bar takes its place and nothing moves.
8
+ */
9
+ export declare function ServerTableControls({ bar, inline, children, }: {
10
+ /** The selection bar; `null` while nothing is selected. */
11
+ bar: ReactNode;
12
+ /** `bandActions: 'inline'`: the zone keeps a phone's row with a lone icon action. */
13
+ inline: boolean;
14
+ /** The search landmark. */
15
+ children: ReactNode;
16
+ }): import("react").JSX.Element;
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * "Nothing matches": the user's filters that narrow the list, as chips
3
3
  * removed by their ✕ (a kept field, a widening switch such as "Show archived" or a scope such as the period, is not
4
- * one, a locked condition stays in the band), then "Clear all" while two
5
- * or a search remain. A removal focuses the next chip, then "Clear all",
4
+ * one, a locked condition stays in the band), then "Clear all" (worded by
5
+ * `empty.clear`) whenever a chip or a search remains. A removal focuses the next chip, then "Clear all",
6
6
  * then the search (the core's `focusAfterRemove`, from `empty`).
7
7
  */
8
- export declare function ServerTableEmptyChips(): import("react").JSX.Element | null;
8
+ export declare function ServerTableEmptyChips({ clear }: {
9
+ clear?: string;
10
+ }): import("react").JSX.Element | null;
@@ -6,9 +6,11 @@ import { useServerTable } from '../use-server-table.js';
6
6
  * page), and the empty page, which stays while the next answer loads.
7
7
  * Both follow the app's `loading` only: a write still unanswered holds
8
8
  * back what is told, never the table. */
9
- export declare function ServerTableGrid<T extends RowData>({ props, state, tableRoot, }: {
9
+ export declare function ServerTableGrid<T extends RowData>({ props, state, tableRoot, hosted, }: {
10
10
  props: ServerTableProps<T>;
11
11
  state: ReturnType<typeof useServerTable<T>>;
12
12
  /** The stable outer table element, for the bulk buttons' focus. */
13
13
  tableRoot: () => HTMLElement | null;
14
+ /** The band's selection bar holds the bulk actions: no toolbar row (#1718). */
15
+ hosted?: boolean;
14
16
  }): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { RowData } from '@tanstack/react-table';
2
+ import { ReactNode } from 'react';
3
+ import { ServerTableProps } from '../types.js';
4
+ import { useServerTable } from '../use-server-table.js';
5
+ /**
6
+ * The selection mode of the band: it is mounted only while rows are
7
+ * selected, over the filter bar (which stays mounted, hidden). The count is
8
+ * not a live region: the footer's polite status tells it once.
9
+ */
10
+ export declare function ServerTableSelectionBar<T extends RowData>({ props, state, tableRoot, phone, onCancel, }: {
11
+ props: ServerTableProps<T>;
12
+ state: ReturnType<typeof useServerTable<T>>;
13
+ tableRoot: () => HTMLElement | null;
14
+ /** Below 768px: the first bulk action keeps its button, the rest go into More. */
15
+ phone: boolean;
16
+ onCancel: () => void;
17
+ }): ReactNode;
@@ -0,0 +1,15 @@
1
+ import { RowData } from '@tanstack/react-table';
2
+ import { RefObject } from 'react';
3
+ import { ServerTableProps } from '../types.js';
4
+ import { TableAnswer } from '../use-table-answer.js';
5
+ export type Scope = {
6
+ /** The bar's focus root: the whole list, its chips row and the page's
7
+ * actions (a `FilterSheetTrigger` placed there) included. */
8
+ rootRef?: RefObject<HTMLElement | null>;
9
+ focusSearch: () => void;
10
+ };
11
+ export declare function ServerTableView<T extends RowData>({ props, answer, scope, }: {
12
+ props: ServerTableProps<T>;
13
+ answer: TableAnswer;
14
+ scope?: Scope;
15
+ }): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { RowData } from '@tanstack/react-table';
2
+ import { ServerTableProps } from '../types.js';
3
+ /** A phone's second header row for a list in cards or tiles (#1719): whether
4
+ * it is drawn (`inRow`), its two slot elements and the context value that
5
+ * hands them to the list bar. */
6
+ export declare function useServerTablePhoneRow<T extends RowData>(props: ServerTableProps<T>): {
7
+ inRow: boolean;
8
+ slots: {
9
+ start: HTMLElement;
10
+ sort: HTMLElement;
11
+ } | null;
12
+ setStart: import('react').Dispatch<import('react').SetStateAction<HTMLElement | null>>;
13
+ setSort: import('react').Dispatch<import('react').SetStateAction<HTMLElement | null>>;
14
+ };
@@ -0,0 +1,24 @@
1
+ import { RowData } from '@tanstack/react-table';
2
+ import { ReactNode, RefObject } from 'react';
3
+ import { ServerTableProps } from '../types.js';
4
+ import { useServerTable } from '../use-server-table.js';
5
+ /**
6
+ * Where the selection shows (`bulkActions`, rows selected):
7
+ * - `bar`: the band's selection bar (#1718), in place of the filter bar and
8
+ * the page's actions. It needs the Filter's bar to replace, a single row for
9
+ * it (not a phone's second row, not the facets panel); otherwise `hosted`
10
+ * is false and the table's toolbar keeps the bulk actions;
11
+ * - `phoneBulk`: a phone's second row (#1719) holds them instead.
12
+ */
13
+ export declare function useServerTableSelectionSlots<T extends RowData>({ props, state, tableRoot, listRef, inRow, }: {
14
+ props: ServerTableProps<T>;
15
+ state: ReturnType<typeof useServerTable<T>>;
16
+ tableRoot: () => HTMLElement | null;
17
+ listRef: RefObject<HTMLElement | null>;
18
+ /** A phone's second row hosts the list bar. */
19
+ inRow: boolean;
20
+ }): {
21
+ hosted: boolean;
22
+ bar: ReactNode;
23
+ phoneBulk: ReactNode;
24
+ };
@@ -0,0 +1,17 @@
1
+ import { PagingNames } from '@nxgt/material-core/table-url';
2
+ /** The footer and paging props of `ServerTable`, apart from the page's data. */
3
+ export type ServerTablePagingProps = {
4
+ /** How the footer's Previous and Next are drawn: `'labelled'` (default) or
5
+ * `'icon'`, icon-only buttons with a tooltip and a name that says the page
6
+ * ("Previous page"); a page given as an href stays a link. */
7
+ pageControls?: 'labelled' | 'icon';
8
+ /** Hides the footer's range and Previous / Next when the result is a single
9
+ * page (no previous page, no next page). Default `false`. The count is
10
+ * still announced by the live region, but no longer shown: show it in the
11
+ * `description` or keep the footer. A selection's "N rows selected" stays. */
12
+ hideOnSinglePage?: boolean;
13
+ /** A page's href. Default ``(params) => `?${params}` ``. */
14
+ pageHref?: (params: URLSearchParams) => string;
15
+ /** The cursor's search param names. Default `after` and `trail`. */
16
+ pagingNames?: Partial<PagingNames>;
17
+ };
@@ -1,7 +1,7 @@
1
1
  import { FilterDefaults, FilterFieldErrors, FilterLockedCondition, FilterModel } from '@nxgt/material-core/filter';
2
2
  import { IconStyleInput } from '@nxgt/material-core/icons';
3
3
  import { ErrorStateKind } from '@nxgt/material-core/states';
4
- import { PagingNames, TableFilterBinding, TableSorting } from '@nxgt/material-core/table-url';
4
+ import { TableFilterBinding, TableSorting } from '@nxgt/material-core/table-url';
5
5
  import { RowData } from '@tanstack/react-table';
6
6
  import { ReactNode, Ref } from 'react';
7
7
  import { StateHeadingLevel } from '../../feedback/state-frame/state-frame.js';
@@ -9,6 +9,7 @@ import { DataTableProps } from '../data-table/types.js';
9
9
  import { FilterBarFieldProps, FilterQueryProps } from '../filter/internal.js';
10
10
  import { ListEmptyContent } from '../list-empty/list-empty.js';
11
11
  import { ServerTableBulkAction } from './bulk-action.js';
12
+ import { ServerTablePagingProps } from './types-paging.js';
12
13
  /** What a bulk action can do to the selection once it acted. */
13
14
  export type ServerTableSelection = {
14
15
  /** Empties the selection; the table takes the focus the toolbar had. */
@@ -123,7 +124,7 @@ export type ServerTableFilterHandle = {
123
124
  };
124
125
  /** The `DataTable` props `ServerTable` passes through as they are. */
125
126
  export type PassedThrough<T extends RowData> = Pick<DataTableProps<T>, 'columns' | 'maxHeight' | 'scrollLabel' | 'showViewOptions' | 'renderExpandedRow' | 'options' | 'loading' | 'loadingRows' | 'getRowHref' | 'onRowClick' | 'linkComponent' | 'density' | 'layout' | 'cardDensity' | 'renderCard' | 'renderTile' | 'enableRowSelection' | 'rowSelectionDisabledReason'>;
126
- export type ServerTableProps<T extends RowData> = PassedThrough<T> & {
127
+ export type ServerTableProps<T extends RowData> = PassedThrough<T> & ServerTablePagingProps & {
127
128
  /** The URL's search params, as the router reads them. */
128
129
  params: URLSearchParams;
129
130
  /** The router's setter, called with new search params: React Router's
@@ -172,10 +173,6 @@ export type ServerTableProps<T extends RowData> = PassedThrough<T> & {
172
173
  * half the room above and under it (a list under a sticky app bar). The
173
174
  * controls keep their size (the Filter's `density` is theirs). */
174
175
  bandDensity?: 'comfortable' | 'compact';
175
- /** How the footer's Previous and Next are drawn: `'labelled'` (default) or
176
- * `'icon'`, icon-only buttons with a tooltip and a name that says the page
177
- * ("Previous page"); a page given as an href stays a link. */
178
- pageControls?: 'labelled' | 'icon';
179
176
  /** With `filter`: a handle to focus the Filter's first control, for the
180
177
  * app to move the focus there (after its own action). */
181
178
  filterRef?: Ref<ServerTableFilterHandle>;
@@ -191,10 +188,6 @@ export type ServerTableProps<T extends RowData> = PassedThrough<T> & {
191
188
  * across pages, and a new query empties the selection. Which rows can be
192
189
  * is `enableRowSelection`; why one cannot, `rowSelectionDisabledReason`. */
193
190
  bulkActions?: ((ids: string[], selection: ServerTableSelection) => ReactNode) | readonly ServerTableBulkAction<T>[];
194
- /** A page's href. Default ``(params) => `?${params}` ``. */
195
- pageHref?: (params: URLSearchParams) => string;
196
- /** The cursor's search param names. Default `after` and `trail`. */
197
- pagingNames?: Partial<PagingNames>;
198
191
  /** Without `filter`: what the live region says once a new query is
199
192
  * answered. Default "N results" (`material.server-table.results`). */
200
193
  resultsLabel?: (count: number) => string;
@@ -0,0 +1,14 @@
1
+ import { RefObject } from 'react';
2
+ /** The element that gets the focus back once the selection bar is gone: the
3
+ * control that started the selection when it is still on the page, else the
4
+ * list. */
5
+ export declare function focusAfterCancel(starter: HTMLElement | null, list: HTMLElement | null): HTMLElement | null;
6
+ /**
7
+ * The focus of the selection band (#1718). On the first selection it keeps
8
+ * the control that had the focus inside the list (the row's box, the
9
+ * header's); `cancel()` marks that the bar's own Cancel is the cause, and
10
+ * once the bar has unmounted the focus goes back to that control, or else to
11
+ * the list. A selection cleared another way (a bulk action's
12
+ * `selection.clear()`, a new query) keeps its own focus handling.
13
+ */
14
+ export declare function useSelectionBand(selecting: boolean, root: RefObject<HTMLElement | null>, list: RefObject<HTMLElement | null>): () => void;
@@ -1,15 +1,17 @@
1
- import { ReactNode } from 'react';
1
+ import { ComponentProps, ReactNode } from 'react';
2
2
  import { StepUpDialogProps } from '../types.js';
3
- type Props = Pick<StepUpDialogProps, 'via' | 'requestError' | 'confirming' | 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'pending' | 'onSubmit' | 'onResend' | 'resent' | 'length' | 'allowRecovery' | 'icons'> & {
3
+ import { StepUpRequestError } from './step-up-request-error.js';
4
+ type Props = Pick<StepUpDialogProps, 'via' | 'requestError' | 'confirming' | 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'pending' | 'onSubmit' | 'onResend' | 'resent' | 'length' | 'allowRecovery' | 'autoFocus' | 'icons'> & {
4
5
  formId: string;
5
6
  labels: NonNullable<StepUpDialogProps['labels']>;
6
7
  /** What is said instead of the field (requesting, confirming). */
7
8
  statusText: ReactNode;
9
+ retry: Omit<ComponentProps<typeof StepUpRequestError>, 'requestError'>;
8
10
  };
9
11
  /**
10
12
  * What sits between the title and the footer: the code form, or, when it is
11
13
  * not there (a code still being requested, a request that failed, an
12
14
  * accepted code), the status line or the alert that replaces it.
13
15
  */
14
- export declare function StepUpBody({ via, requestError, confirming, formId, labels, statusText, icons, ...code }: Props): import("react").JSX.Element;
16
+ export declare function StepUpBody({ via, requestError, confirming, formId, labels, statusText, icons, retry, ...code }: Props): import("react").JSX.Element;
15
17
  export {};
@@ -0,0 +1,15 @@
1
+ import { FocusEvent, ReactNode, RefObject } from 'react';
2
+ type Props = {
3
+ requestError: ReactNode;
4
+ /** The "Retry" button is drawn only with a handler. */
5
+ onRetry?: () => void;
6
+ retryLabel: string;
7
+ retrying: boolean;
8
+ /** Retries that finished: a new key tells the live region again, even for the same text. */
9
+ settled: number;
10
+ retryRef: RefObject<HTMLButtonElement | null>;
11
+ onRetryBlur: (event: FocusEvent) => void;
12
+ };
13
+ /** The alert that replaces the field when the code could not be requested, with "Retry" when the host offers it. */
14
+ export declare function StepUpRequestError({ requestError, onRetry, retryLabel, retrying, settled, retryRef, onRetryBlur, }: Props): import("react").JSX.Element;
15
+ export {};
@@ -7,10 +7,13 @@ import { StepUpDialogProps } from './types.js';
7
7
  * `error`, `pending`, `resent`, `onSubmit`, `onResend`), which the app
8
8
  * wires to its own model.
9
9
  *
10
- * The title takes the focus on open and whenever the field goes (a code
10
+ * The title takes the focus on open (unless `autoFocus` sends it to the
11
+ * field) and whenever the field goes (a code
11
12
  * being requested, a code accepted); the field takes it after a refusal; on
12
13
  * close it goes back to what opened the dialog. Escape, a click outside and
13
14
  * Cancel call `onCancel`, except while `confirming`. A locked code leaves
14
- * Cancel usable.
15
+ * Cancel usable. A failed code request (`requestError`) offers "Retry" when
16
+ * `onRetry` is set: the focus stays on it while it runs and goes to the
17
+ * field once the request succeeds.
15
18
  */
16
- export declare function StepUpDialog({ open, onCancel, cancelVariant, via, destination, requestError, confirming, confirmedLabel, title, description, labels: labelOverrides, icons, ...code }: StepUpDialogProps): import("react").JSX.Element;
19
+ export declare function StepUpDialog({ open, onCancel, cancelVariant, via, destination, requestError, onRetry, confirming, confirmedLabel, title, description, labels: labelOverrides, icons, ...code }: StepUpDialogProps): import("react").JSX.Element;
@@ -19,8 +19,10 @@ export type StepUpDialogLabels = {
19
19
  cancel: string;
20
20
  /** Said once the code was accepted and the host finishes its action. */
21
21
  confirmed: string;
22
+ /** The "Retry" button of a failed code request (see `onRetry`). */
23
+ retry: string;
22
24
  };
23
- export type StepUpDialogProps = Pick<VerificationCodeProps, 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'pending' | 'onSubmit' | 'onResend' | 'resent' | 'length' | 'allowRecovery'> & {
25
+ export type StepUpDialogProps = Pick<VerificationCodeProps, 'attemptsLeft' | 'locked' | 'error' | 'retryAfter' | 'pending' | 'onSubmit' | 'onResend' | 'resent' | 'length' | 'allowRecovery' | 'autoFocus'> & {
24
26
  open: boolean;
25
27
  /**
26
28
  * Escape, a click outside and Cancel call it, except while `confirming`.
@@ -38,6 +40,15 @@ export type StepUpDialogProps = Pick<VerificationCodeProps, 'attemptsLeft' | 'lo
38
40
  destination?: ReactNode;
39
41
  /** The request for a code failed; shown as an alert in place of the field. */
40
42
  requestError?: ReactNode;
43
+ /**
44
+ * Draws a "Retry" button in the `requestError` alert. Pressing it calls
45
+ * this; while the returned promise is pending the button is busy and keeps
46
+ * the focus. Answer by clearing `requestError` and setting `via` (the code
47
+ * field takes the focus) or by setting a new `requestError` (the focus
48
+ * stays on "Retry" and the new text is announced). Left out, the alert
49
+ * has no button.
50
+ */
51
+ onRetry?: () => unknown;
41
52
  /**
42
53
  * The code was accepted and the host re-runs its action: the field goes,
43
54
  * a status line shows `labels.confirmed` and Cancel is disabled until the
@@ -0,0 +1,27 @@
1
+ import { RefObject } from 'react';
2
+ type Input = {
3
+ open: boolean;
4
+ fieldShown: boolean;
5
+ requestError: unknown;
6
+ confirming: boolean;
7
+ formId: string;
8
+ titleRef: RefObject<HTMLElement | null>;
9
+ };
10
+ /**
11
+ * Where the focus goes around a "Retry": it stays on the button while the
12
+ * retry runs and when the request fails again (the button may be taken away
13
+ * and put back by the host meanwhile, the title holding the focus in the
14
+ * gap), and goes to the code field once the request succeeds. Only after a
15
+ * press of "Retry", and only while the focus is still free (the page, the
16
+ * dialog itself, the title or the button): a focus the user moved elsewhere is left alone.
17
+ */
18
+ export declare function useRetryFocus({ open, fieldShown, requestError, confirming, formId, titleRef, }: Input): {
19
+ retryRef: RefObject<HTMLButtonElement | null>;
20
+ /** On "Retry": the focus it holds is followed from here on. */
21
+ arm: () => void;
22
+ /** On the button's blur: a focus that went to another control is not ours any more. */
23
+ release: (event: {
24
+ relatedTarget: EventTarget | null;
25
+ }) => void;
26
+ };
27
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The retry of a failed code request: `run` calls the host's `onRetry` and
3
+ * stays `retrying` until what it returned settles (a thrown or rejected
4
+ * retry is the host's to show as a new `requestError`). `settled` counts the
5
+ * retries that finished, so the alert is told again, even for the same text.
6
+ */
7
+ export declare function useRetry(onRetry: (() => unknown) | undefined): {
8
+ retrying: boolean;
9
+ settled: number;
10
+ run: () => Promise<void>;
11
+ };