@masmarino/gabarit 1.3.0 → 2.0.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.
@@ -1,3 +1,5 @@
1
+ @use 'a11y';
2
+
1
3
  .gbt-form-error {
2
4
  margin: 0 0 0.75rem;
3
5
  font-size: 0.875rem;
@@ -85,6 +87,11 @@
85
87
  }
86
88
  }
87
89
 
90
+ // Global to reach the projected links: a rail taller than the window scrolls instead of squeezing them.
91
+ .gbt-app-shell__nav > * {
92
+ flex-shrink: 0;
93
+ }
94
+
88
95
  .gbt-app-shell__link {
89
96
  position: relative;
90
97
  display: flex;
@@ -95,6 +102,7 @@
95
102
  border-radius: var(--site-border-radius-sm);
96
103
  color: var(--text-secondary);
97
104
  font-size: 0.875rem;
105
+ font-weight: 500;
98
106
  text-decoration: none;
99
107
  overflow: hidden;
100
108
  white-space: nowrap;
@@ -112,16 +120,15 @@
112
120
  }
113
121
 
114
122
  &:focus-visible {
115
- outline: 2px solid var(--gbt-focus-ring, var(--primary));
116
- outline-offset: -2px;
123
+ @include a11y.focus-ring(-2px);
117
124
  }
118
125
 
119
126
  // An app can tone the current page down to a tint with a mark on its edge (--gbt-nav-active-*).
120
127
  &[aria-current] {
121
- background: var(--gbt-nav-active-bg, var(--primary));
122
- color: var(--gbt-nav-active-text, var(--text-on-primary));
128
+ background: var(--gbt-nav-active-bg, color-mix(in srgb, var(--text-primary) 9%, transparent));
129
+ color: var(--gbt-nav-active-text, var(--text-primary));
123
130
  font-weight: 600;
124
- box-shadow: inset 2px 0 0 var(--gbt-nav-active-mark, transparent);
131
+ box-shadow: inset 2px 0 0 var(--gbt-nav-active-mark, var(--accent));
125
132
  }
126
133
  }
127
134
 
@@ -217,7 +224,7 @@
217
224
  gap: 0.5rem;
218
225
  width: 100%;
219
226
  padding: 8px 10px;
220
- border-radius: var(--gbt-radius-menu, 8px);
227
+ border-radius: var(--gbt-radius-menu, 4px);
221
228
  color: var(--text-primary);
222
229
  font-size: 14px;
223
230
  text-align: left;
@@ -232,8 +239,7 @@
232
239
  }
233
240
 
234
241
  &:focus-visible {
235
- outline: 2px solid var(--gbt-focus-ring, var(--primary));
236
- outline-offset: -2px;
242
+ @include a11y.focus-ring(-2px);
237
243
  }
238
244
  }
239
245
 
@@ -1,3 +1,6 @@
1
1
  @forward 'palette';
2
2
  @forward 'semantic';
3
+ @forward 'themes';
4
+ @forward 'a11y';
5
+ @forward 'base';
3
6
  @forward 'utilities';
@@ -0,0 +1,345 @@
1
+ import * as i0 from "@angular/core";
2
+ import { InjectionToken, Provider, Signal } from "@angular/core";
3
+ import { Observable } from "rxjs";
4
+ import { CanActivateFn, Routes } from "@angular/router";
5
+ import { SafeHtml } from "@angular/platform-browser";
6
+ import { AutocompleteSearchFn, PanelHeadingLevel } from "@masmarino/gabarit";
7
+ interface DocsConfig {
8
+ /** Where the files (`<root>/index.json`, `<root>/<section>/<page>.md`) and the routes live. `/docs` by default. */
9
+ root: string;
10
+ /** A quote opening on one of these words in bold (`> **Note** …`) becomes a callout of that tone. Any case. */
11
+ callouts: Readonly<Record<string, 'note' | 'warning'>>;
12
+ }
13
+ export declare const DEFAULT_DOCS_CONFIG: Readonly<DocsConfig>;
14
+ export declare const DOCS_CONFIG: InjectionToken<DocsConfig>;
15
+ /**
16
+ * Gets the shown page's title (or "not found", or the reader's name while loading), for an app that shows titles in
17
+ * its own header. Optional.
18
+ */
19
+ export declare const DOCS_TITLE: InjectionToken<(title: string) => void>;
20
+ export declare function provideDocs(config?: Partial<DocsConfig>): Provider;
21
+ /** Every string the documentation reader shows or announces. English by default. */
22
+ interface DocsLabels {
23
+ /** The reader's name: the navigation's heading, its landmark and the breadcrumb's first step. */
24
+ documentation: string;
25
+ showContents: string;
26
+ hideContents: string;
27
+ searchLabel: string;
28
+ searchPlaceholder: string;
29
+ searching: string;
30
+ noResults: string;
31
+ searchFailed: string;
32
+ results: (count: number) => string;
33
+ onThisPage: string;
34
+ breadcrumb: string;
35
+ neighbours: string;
36
+ previous: string;
37
+ next: string;
38
+ notFoundHeading: string;
39
+ notFoundMessage: string;
40
+ toStart: string;
41
+ loadFailed: string;
42
+ retry: string;
43
+ loading: string;
44
+ /** The accessible names given to a code block and a table, which scroll sideways and so take the focus. */
45
+ codeBlock: string;
46
+ table: string;
47
+ }
48
+ export declare const DEFAULT_DOCS_LABELS: Readonly<DocsLabels>;
49
+ export declare const DOCS_LABELS: InjectionToken<Partial<DocsLabels>>;
50
+ /** The reader's strings, over the English defaults; the ones left out keep theirs. */
51
+ export declare function provideDocsLabels(labels: Partial<DocsLabels>): Provider;
52
+ export declare function docsLabels(): Signal<DocsLabels>;
53
+ interface DocsPageEntry {
54
+ slug: string;
55
+ title: string;
56
+ description: string;
57
+ }
58
+ interface DocsSection {
59
+ slug: string;
60
+ title: string;
61
+ pages: DocsPageEntry[];
62
+ }
63
+ /** `<root>/index.json`: the sections and their pages, in reading order. */
64
+ interface DocsIndex {
65
+ sections: DocsSection[];
66
+ }
67
+ interface DocsLink {
68
+ sectionTitle: string;
69
+ title: string;
70
+ commands: string[];
71
+ }
72
+ /** A page with its neighbours in reading order, across sections. */
73
+ interface DocsLocation {
74
+ section: DocsSection;
75
+ page: DocsPageEntry;
76
+ previous: DocsLink | null;
77
+ next: DocsLink | null;
78
+ }
79
+ export declare function docsPageCommands(root: string, section: string, page: string): string[];
80
+ /** Every page in reading order, each with its section. */
81
+ export declare function docsReadingOrder(index: DocsIndex): {
82
+ section: DocsSection;
83
+ page: DocsPageEntry;
84
+ }[];
85
+ /** Where `<root>` leads: the first page of the first section, or `null` for an empty index. */
86
+ export declare function firstDocsPage(root: string, index: DocsIndex): string[] | null;
87
+ export declare function locateDocsPage(root: string, index: DocsIndex, section: string | null, page: string | null): DocsLocation | null;
88
+ /** Fetches the index and each page once; they only change with a new app version. Failures aren't cached. */
89
+ export declare class DocsService {
90
+ private readonly http;
91
+ readonly root: string;
92
+ private index$;
93
+ private readonly pages;
94
+ index(): Observable<DocsIndex>;
95
+ /** The page's Markdown. A missing file fails with a 404, including when the server answers with the app shell. */
96
+ page(section: string, page: string): Observable<string>;
97
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocsService, never>;
98
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
99
+ }
100
+ export declare const isNotFound: (error: unknown) => boolean;
101
+ export declare const DOCS_SEARCH_LIMIT = 8;
102
+ interface DocsSearchHit {
103
+ sectionTitle: string;
104
+ pageTitle: string;
105
+ commands: string[];
106
+ /** Id of the best matching heading (`user-content-…`), so the result lands on it. */
107
+ fragment: string | null;
108
+ heading: string | null;
109
+ /** Body text around the first match, or the page's description when only the title or headings match. */
110
+ excerpt: {
111
+ before: string;
112
+ match: string;
113
+ after: string;
114
+ };
115
+ }
116
+ export declare function searchTokens(query: string): string[];
117
+ /** Title, headings and text of a page. Heading ids must match gbt-markdown-view's (`-2`, `-3` on repeats). */
118
+ export declare function parseDocsPage(markdown: string): {
119
+ headings: {
120
+ id: string;
121
+ text: string;
122
+ }[];
123
+ body: string;
124
+ };
125
+ /**
126
+ * Searches every page in the browser, fetching them on first use. All words must match; title beats heading beats
127
+ * text.
128
+ */
129
+ export declare class DocsSearchService {
130
+ private docs;
131
+ private documents;
132
+ /** Starts loading the pages before the first search; the field calls it on focus. */
133
+ prepare(): void;
134
+ private load;
135
+ search(query: string): Promise<DocsSearchHit[]>;
136
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocsSearchService, never>;
137
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
138
+ }
139
+ /** Sends the root to the first page. A broken or empty index is left for the reader to show. */
140
+ export declare const docsHomeGuard: CanActivateFn;
141
+ /** The reader's routes, for the configured root. `page` loads the component that shows it (often the app's). */
142
+ export declare function docsRoutes(page: () => Promise<unknown>): Routes;
143
+ /** The left column: search, then the sections and their pages, only the current one open. */
144
+ export declare class DocsNav {
145
+ index: import("@angular/core").InputSignal<DocsIndex>;
146
+ section: import("@angular/core").InputSignal<string | null>;
147
+ page: import("@angular/core").InputSignal<string | null>;
148
+ private readonly root;
149
+ protected readonly labels: import("@angular/core").Signal<import("@masmarino/gabarit/docs").DocsLabels>;
150
+ protected readonly bodyId: string;
151
+ protected readonly navOpen: import("@angular/core").WritableSignal<boolean>;
152
+ private readonly toggled;
153
+ protected readonly sections: import("@angular/core").Signal<{
154
+ slug: string;
155
+ title: string;
156
+ open: boolean;
157
+ pages: {
158
+ slug: string;
159
+ title: string;
160
+ commands: string[];
161
+ current: boolean;
162
+ }[];
163
+ }[]>;
164
+ protected setOpen(slug: string, open: boolean): void;
165
+ protected close(): void;
166
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocsNav, never>;
167
+ static ɵcmp: i0.ɵɵComponentDeclaration<DocsNav, "gbt-docs-nav", never, {
168
+ "index": {
169
+ "alias": "index";
170
+ "required": true;
171
+ "isSignal": true;
172
+ };
173
+ "section": {
174
+ "alias": "section";
175
+ "required": false;
176
+ "isSignal": true;
177
+ };
178
+ "page": {
179
+ "alias": "page";
180
+ "required": false;
181
+ "isSignal": true;
182
+ };
183
+ }, {}, never, never, true, never>;
184
+ }
185
+ /** One heading of the rendered content, for an "On this page" outline. */
186
+ interface MarkdownOutlineEntry {
187
+ /** The level as rendered, after `headingOffset`: 2, 3 or 4. */
188
+ level: number;
189
+ text: string;
190
+ id: string;
191
+ }
192
+ /** GitHub-like slug, accents kept. `section` when nothing is left, e.g. a title made only of emoji. */
193
+ export declare function headingSlug(text: string): string;
194
+ export declare function decodeFragment(rawFragment: string): string;
195
+ /** The element a `#fragment` points at: the plain `id`, else the `user-content-` id or `<a name>` the sanitiser made. */
196
+ export declare function findAnchorTarget(root: HTMLElement, rawFragment: string): HTMLElement | null;
197
+ /** A keyboard only scrolls a wide code block or table it has focused (WCAG 2.1.1): each gets a tab stop. */
198
+ export declare function makeScrollableBlocksFocusable(container: HTMLElement, names: {
199
+ codeBlock: string;
200
+ table: string;
201
+ }): void;
202
+ /** Names each task-list checkbox after its item, so a screen reader says what's done. */
203
+ export declare function nameTaskCheckboxes(container: HTMLElement): void;
204
+ /**
205
+ * Markdown rendered to sanitised HTML, with the reading styles of the design system: headings, lists, code, tables,
206
+ * quotes. Every heading gets a stable id, and the h2–h4 outline is emitted after each render.
207
+ */
208
+ export declare class MarkdownView {
209
+ content: import("@angular/core").InputSignal<string>;
210
+ /** Levels added to every heading (up to h6), so a `# Title` under the page's own headings keeps the outline. */
211
+ headingOffset: import("@angular/core").InputSignal<number>;
212
+ /** Links under this prefix (say `/docs`) go through the router instead of reloading the app. Off by default. */
213
+ routedLinkPrefix: import("@angular/core").InputSignal<string | null>;
214
+ /** The h2–h4 headings, emitted after each render once their ids are in the DOM. */
215
+ outline: import("@angular/core").OutputEmitterRef<MarkdownOutlineEntry[]>;
216
+ private readonly sanitizer;
217
+ private readonly router;
218
+ private readonly labels;
219
+ private readonly container;
220
+ constructor();
221
+ /**
222
+ * A bare #anchor resolves against <base href="/"> and would load the home page, so a plain click scrolls here
223
+ * instead. Modified and middle clicks are the browser's.
224
+ */
225
+ protected onClick(event: MouseEvent): void;
226
+ /** The `href` of a clicked in-content link under `routedLinkPrefix`, or `null` when the browser should follow it. */
227
+ private routedHref;
228
+ protected readonly renderedHtml: import("@angular/core").Signal<SafeHtml>;
229
+ static ɵfac: i0.ɵɵFactoryDeclaration<MarkdownView, never>;
230
+ static ɵcmp: i0.ɵɵComponentDeclaration<MarkdownView, "gbt-markdown-view", never, {
231
+ "content": {
232
+ "alias": "content";
233
+ "required": true;
234
+ "isSignal": true;
235
+ };
236
+ "headingOffset": {
237
+ "alias": "headingOffset";
238
+ "required": false;
239
+ "isSignal": true;
240
+ };
241
+ "routedLinkPrefix": {
242
+ "alias": "routedLinkPrefix";
243
+ "required": false;
244
+ "isSignal": true;
245
+ };
246
+ }, {
247
+ "outline": "outline";
248
+ }, never, never, true, never>;
249
+ }
250
+ type DocsView = {
251
+ kind: 'loading';
252
+ } | {
253
+ kind: 'failed';
254
+ } | {
255
+ kind: 'not-found';
256
+ firstPage: string[] | null;
257
+ } | {
258
+ kind: 'page';
259
+ location: DocsLocation;
260
+ content: string;
261
+ };
262
+ /** The routed page with its nav, breadcrumb, neighbours and outline, or a "not found" in the same frame. */
263
+ export declare class DocsPage {
264
+ private readonly docs;
265
+ private readonly route;
266
+ private readonly setTitle;
267
+ private readonly callouts;
268
+ private readonly host;
269
+ protected readonly labels: import("@angular/core").Signal<import("@masmarino/gabarit/docs").DocsLabels>;
270
+ protected readonly root: string;
271
+ protected readonly skeletonRows: string[];
272
+ private readonly reload$;
273
+ protected readonly index: import("@angular/core").WritableSignal<DocsIndex | null>;
274
+ private readonly params;
275
+ protected readonly sectionSlug: import("@angular/core").Signal<string | null>;
276
+ protected readonly pageSlug: import("@angular/core").Signal<string | null>;
277
+ protected readonly view: import("@angular/core").Signal<DocsView>;
278
+ protected readonly page: import("@angular/core").Signal<{
279
+ kind: "page";
280
+ location: DocsLocation;
281
+ content: string;
282
+ } | null>;
283
+ protected readonly notFound: import("@angular/core").Signal<{
284
+ kind: "not-found";
285
+ firstPage: string[] | null;
286
+ } | null>;
287
+ protected readonly outline: import("@angular/core").WritableSignal<MarkdownOutlineEntry[]>;
288
+ protected readonly showOutline: import("@angular/core").Signal<boolean>;
289
+ private wanted;
290
+ private renderedKey;
291
+ constructor();
292
+ private load;
293
+ protected retry(): void;
294
+ protected sectionLink(location: DocsLocation): string[];
295
+ /** After each render: the outline, the callouts, then the pending navigation. */
296
+ protected onRendered(entries: MarkdownOutlineEntry[]): void;
297
+ private content;
298
+ /** Scrolls to the `#fragment` (an outline `user-content-…` id or the bare slug from a link), or to the top of a new page. */
299
+ private settle;
300
+ private focus;
301
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocsPage, never>;
302
+ static ɵcmp: i0.ɵɵComponentDeclaration<DocsPage, "gbt-docs-page", never, {}, {}, never, never, true, never>;
303
+ }
304
+ /** The search field above the documentation's navigation. Pages load on first focus, since most visits never search. */
305
+ export declare class DocsSearch {
306
+ /** Emitted once a result is opened, so a folded navigation can close. */
307
+ opened: import("@angular/core").OutputEmitterRef<DocsSearchHit>;
308
+ private readonly searchService;
309
+ private readonly router;
310
+ private readonly field;
311
+ protected readonly labels: import("@angular/core").Signal<import("@masmarino/gabarit/docs").DocsLabels>;
312
+ protected readonly search: AutocompleteSearchFn<DocsSearchHit>;
313
+ protected readonly label: (hit: DocsSearchHit) => string;
314
+ protected readonly announce: (count: number) => string;
315
+ protected prepare(): void;
316
+ protected open(hit: DocsSearchHit): void;
317
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocsSearch, never>;
318
+ static ɵcmp: i0.ɵɵComponentDeclaration<DocsSearch, "gbt-docs-search", never, {}, {
319
+ "opened": "opened";
320
+ }, never, never, true, never>;
321
+ }
322
+ /** An outline is worth a panel from two headings on: one heading is no table of contents. */
323
+ export declare function hasOutline(entries: readonly MarkdownOutlineEntry[]): boolean;
324
+ /** "On this page" for rendered Markdown. The router doesn't scroll to anchors, so a click does it here. */
325
+ export declare class MarkdownOutline {
326
+ entries: import("@angular/core").InputSignal<MarkdownOutlineEntry[]>;
327
+ headingLevel: import("@angular/core").InputSignal<PanelHeadingLevel>;
328
+ protected readonly labels: import("@angular/core").Signal<import("@masmarino/gabarit/docs").DocsLabels>;
329
+ protected readonly here: readonly string[];
330
+ protected goTo(id: string): void;
331
+ static ɵfac: i0.ɵɵFactoryDeclaration<MarkdownOutline, never>;
332
+ static ɵcmp: i0.ɵɵComponentDeclaration<MarkdownOutline, "gbt-markdown-outline", never, {
333
+ "entries": {
334
+ "alias": "entries";
335
+ "required": true;
336
+ "isSignal": true;
337
+ };
338
+ "headingLevel": {
339
+ "alias": "headingLevel";
340
+ "required": false;
341
+ "isSignal": true;
342
+ };
343
+ }, {}, never, never, true, never>;
344
+ }
345
+ export type { DocsConfig, DocsIndex, DocsLabels, DocsLink, DocsLocation, DocsPageEntry, DocsSearchHit, DocsSection, MarkdownOutlineEntry };
@@ -2,7 +2,7 @@ import * as i0 from "@angular/core";
2
2
  import { ElementRef, InjectionToken, Injector, OnDestroy, PipeTransform, Provider, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import { ControlValueAccessor, FormControl } from "@angular/forms";
4
4
  import { Observable } from "rxjs";
5
- export declare const GABARIT_VERSION = "1.3.0";
5
+ export declare const GABARIT_VERSION = "2.0.0";
6
6
  export declare class Icon {
7
7
  private readonly sanitizer;
8
8
  private readonly registry;
@@ -1064,6 +1064,15 @@ type InputSize = 'md' | 'sm';
1064
1064
  type InputInputmode = 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search';
1065
1065
  type InputAutocapitalize = 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';
1066
1066
  type InputEnterkeyhint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
1067
+ /** Makes the field the combobox of a suggestion list the caller renders, with its keys and active option. */
1068
+ interface InputCombobox {
1069
+ /** Whether the listbox is shown. */
1070
+ expanded: boolean;
1071
+ /** The id of the listbox. */
1072
+ controls: string;
1073
+ /** The id of the highlighted option, `null` when none is. */
1074
+ activeDescendant: string | null;
1075
+ }
1067
1076
  export declare class GbtInput implements ControlValueAccessor {
1068
1077
  id: import("@angular/core").InputSignal<string>;
1069
1078
  label: import("@angular/core").InputSignal<string>;
@@ -1085,6 +1094,7 @@ export declare class GbtInput implements ControlValueAccessor {
1085
1094
  maxlength: import("@angular/core").InputSignal<number | null>;
1086
1095
  min: import("@angular/core").InputSignal<string | number | null>;
1087
1096
  max: import("@angular/core").InputSignal<string | number | null>;
1097
+ combobox: import("@angular/core").InputSignal<InputCombobox | null>;
1088
1098
  showPasswordLabel: import("@angular/core").InputSignal<string>;
1089
1099
  hidePasswordLabel: import("@angular/core").InputSignal<string>;
1090
1100
  committed: import("@angular/core").OutputEmitterRef<string>;
@@ -1208,6 +1218,11 @@ export declare class GbtInput implements ControlValueAccessor {
1208
1218
  "required": false;
1209
1219
  "isSignal": true;
1210
1220
  };
1221
+ "combobox": {
1222
+ "alias": "combobox";
1223
+ "required": false;
1224
+ "isSignal": true;
1225
+ };
1211
1226
  "showPasswordLabel": {
1212
1227
  "alias": "showPasswordLabel";
1213
1228
  "required": false;
@@ -4823,10 +4838,7 @@ export declare class ListCard {
4823
4838
  emptyMessage: import("@angular/core").InputSignal<string>;
4824
4839
  emptyIllustration: import("@angular/core").InputSignal<EmptyStateIllustration | null>;
4825
4840
  emptyIcon: import("@angular/core").InputSignal<string | null>;
4826
- /**
4827
- * What sits above the box: the projected `[list-card-header]` (ready), its placeholder (loading,
4828
- * unless `skeletonHeader` is off), or nothing (failed, empty).
4829
- */
4841
+ /** The projected header when ready, its placeholder while loading (unless skeletonHeader is off), else nothing. */
4830
4842
  protected readonly header: import("@angular/core").Signal<"slot" | "skeleton" | null>;
4831
4843
  protected readonly placeholders: import("@angular/core").Signal<string[]>;
4832
4844
  static ɵfac: i0.ɵɵFactoryDeclaration<ListCard, never>;
@@ -5522,7 +5534,8 @@ interface AuthPort {
5522
5534
  authConfig(): Observable<AuthConfig>;
5523
5535
  login(username: string, password: string): Observable<LoginResponse>;
5524
5536
  register(username: string, email: string, password: string): Observable<LoginResponse>;
5525
- activate(token: string, password: string): Observable<void>;
5537
+ /** `username` is passed only when the page lets the invitee choose it (`chooseUsername`). */
5538
+ activate(token: string, password: string, username?: string): Observable<void>;
5526
5539
  resetPassword(token: string, password: string): Observable<void>;
5527
5540
  verifyMfa(mfaToken: string, proof: MfaProof): Observable<void>;
5528
5541
  startPasskeyChallenge(mfaToken: string): Observable<PasskeyChallenge>;
@@ -5721,6 +5734,14 @@ export declare const DEFAULT_REGISTER_LABELS: Readonly<RegisterLabels>;
5721
5734
  interface ActivateLabels extends CommonFailureLabels {
5722
5735
  heading: string;
5723
5736
  intro: string;
5737
+ /** The intro when the invitee chooses their username too (`chooseUsername`). */
5738
+ introWithUsername: string;
5739
+ username: string;
5740
+ usernameHint: string;
5741
+ usernameEmpty: string;
5742
+ usernameInvalid: string;
5743
+ usernameReserved: string;
5744
+ usernameTaken: string;
5724
5745
  password: string;
5725
5746
  passwordHint: (minLength: number) => string;
5726
5747
  confirmation: string;
@@ -5928,7 +5949,7 @@ type PasswordGatedFailure = 'wrong-password' | 'rate-limited' | 'other';
5928
5949
  export declare function classifyPasswordFailure(err: unknown): PasswordGatedFailure;
5929
5950
  export declare function isTooManyPasskeys(err: unknown): boolean;
5930
5951
  type RegisterFailure = 'disabled' | 'invalid' | 'username-invalid' | 'email-invalid' | 'password-weak' | 'username-reserved' | 'username-taken' | 'email-taken' | 'rate-limited' | 'other';
5931
- type ActivateFailure = 'invalid-link' | 'weak-password' | 'rate-limited' | 'other';
5952
+ type ActivateFailure = 'invalid-link' | 'weak-password' | 'username-invalid' | 'username-reserved' | 'username-taken' | 'rate-limited' | 'other';
5932
5953
  export declare function classifyRegisterFailure(err: unknown): RegisterFailure;
5933
5954
  export declare function classifyActivateFailure(err: unknown): ActivateFailure;
5934
5955
  export declare const MIN_PASSWORD_LENGTH = 8;
@@ -6120,6 +6141,8 @@ export declare class MfaEnrollment {
6120
6141
  choosePasskey(): void;
6121
6142
  createPasskey(): void;
6122
6143
  protected back(): void;
6144
+ /** A server that issues no backup codes with this factor has nothing to show: the enrolment ends there. */
6145
+ private enrolled;
6123
6146
  finish(): void;
6124
6147
  private goTo;
6125
6148
  private passkeyFailed;
@@ -6209,7 +6232,7 @@ export declare class AuthLogin {
6209
6232
  };
6210
6233
  }, {
6211
6234
  "loggedIn": "loggedIn";
6212
- }, ["registerLink"], ["[auth-logo]", "[gbtAuthFooterLink]"], true, never>;
6235
+ }, ["registerLink"], ["[auth-logo]", "[auth-notice]", "[gbtAuthFooterLink]"], true, never>;
6213
6236
  }
6214
6237
  type Registration = 'loading' | 'open' | 'closed' | 'created';
6215
6238
  export declare class AuthRegister {
@@ -6283,6 +6306,9 @@ export declare class AuthActivate {
6283
6306
  token: import("@angular/core").InputSignal<string | null>;
6284
6307
  labels: import("@angular/core").InputSignal<Partial<ActivateLabels>>;
6285
6308
  minPasswordLength: import("@angular/core").InputSignal<number>;
6309
+ /** The invitee chooses their username along with the password, for servers that let them. */
6310
+ chooseUsername: import("@angular/core").InputSignal<boolean>;
6311
+ usernamePattern: import("@angular/core").InputSignal<RegExp>;
6286
6312
  activated: import("@angular/core").OutputEmitterRef<void>;
6287
6313
  signIn: import("@angular/core").OutputEmitterRef<void>;
6288
6314
  protected readonly text: import("@angular/core").Signal<Readonly<ActivateLabels>>;
@@ -6291,11 +6317,14 @@ export declare class AuthActivate {
6291
6317
  protected readonly passwordHint: import("@angular/core").Signal<string>;
6292
6318
  private readonly spent;
6293
6319
  view: import("@angular/core").WritableSignal<View$3>;
6320
+ protected username: import("@angular/core").WritableSignal<string>;
6294
6321
  protected password: import("@angular/core").WritableSignal<string>;
6295
6322
  protected confirmation: import("@angular/core").WritableSignal<string>;
6296
6323
  error: import("@angular/core").WritableSignal<string>;
6297
6324
  submitting: import("@angular/core").WritableSignal<boolean>;
6298
6325
  private attempted;
6326
+ protected intro: import("@angular/core").Signal<string>;
6327
+ protected usernameFieldError: import("@angular/core").Signal<string | null>;
6299
6328
  protected passwordFieldError: import("@angular/core").Signal<string | null>;
6300
6329
  protected confirmationFieldError: import("@angular/core").Signal<string | null>;
6301
6330
  constructor();
@@ -6303,6 +6332,7 @@ export declare class AuthActivate {
6303
6332
  private confirmationProblem;
6304
6333
  private clearPasswords;
6305
6334
  private show;
6335
+ private firstField;
6306
6336
  private fail;
6307
6337
  static ɵfac: i0.ɵɵFactoryDeclaration<AuthActivate, never>;
6308
6338
  static ɵcmp: i0.ɵɵComponentDeclaration<AuthActivate, "gbt-auth-activate", never, {
@@ -6321,6 +6351,16 @@ export declare class AuthActivate {
6321
6351
  "required": false;
6322
6352
  "isSignal": true;
6323
6353
  };
6354
+ "chooseUsername": {
6355
+ "alias": "chooseUsername";
6356
+ "required": false;
6357
+ "isSignal": true;
6358
+ };
6359
+ "usernamePattern": {
6360
+ "alias": "usernamePattern";
6361
+ "required": false;
6362
+ "isSignal": true;
6363
+ };
6324
6364
  }, {
6325
6365
  "activated": "activated";
6326
6366
  "signIn": "signIn";
@@ -6556,4 +6596,4 @@ export declare class PasskeySettings {
6556
6596
  "sessionRevoked": "sessionRevoked";
6557
6597
  }, never, never, true, never>;
6558
6598
  }
6559
- export type { AccordionMode, ActivateFailure, ActivateLabels, AlertAppearance, AlertIconAlign, AlertLive, AlertSize, AlertVariant, Arc, AuthConfig, AuthLabels, AuthPort, AuthPortError, AutocompleteSearchFn, AvatarGroupItem, AvatarSize, AxisSpec, BackupCodesLabels, BackupCodesResult, BadgeAppearance, BadgeSize, BadgeVariant, BandScale, ButtonHaspopup, ButtonSize, ButtonVariant, CalendarDay, CardTone, CardVariant, ChartBox, ChartInterval, ChartMargin, ChartPoint, ChartReader, ChartSeries, CheckboxGroupOption, CheckboxGroupSection, ConfirmDangerModalTone, CopyButtonFeedback, CopyOutcome, CopyStatus, CopyValue, DateInput, DateRangeValue, DescriptionListEntry, DescriptionListLayout, DescriptionListResponsive, DescriptionListValueAlign, DimensionRow, DisclosureAppearance, DisclosureHeadingLevel, DividerOrientation, DrawerEdge, EmailProblem, EmptyStateHeadingLevel, EmptyStateIllustration, EmptyStateSize, EmptyStateTone, EnrolledFactor, FlatTreeNode, FormatBytesOptions, FormatDurationOptions, FormatRelativeTimeOptions, FunnelStep, GbtBytesPipeOptions, GbtDateTimePipeOptions, GbtPipeLocale, GbtRelativeTimePipeOptions, GbtToastKind, GbtToastOptions, IconMarkerAppearance, IconMarkerShape, IconMarkerSize, IconMarkerTone, JobGraphJob, JobGraphStage, JobGraphStatus, JobStatusValue, LegendEntry, LinearAxisSpec, ListCardState, ListRowTone, ListToolbarAccessors, ListToolbarDirection, ListToolbarSortOption, ListToolbarSortValue, ListToolbarState, ListToolbarStateConfig, LoginLabels, LoginResponse, MenuItemVariant, MfaEnrollmentLabels, MfaFailure, MfaFormOwner, MfaPort, MfaProof, MfaSettingsLabels, MfaSetupResult, MfaStatus, NavTabsOrientation, NotificationDotVariant, PageHeaderLevel, PageLayoutAsidePosition, PageLayoutAsideWidth, PageLayoutWidth, PanelHeadingLevel, Passkey, PasskeyChallenge, PasskeyFailure, PasskeyNameProblem, PasskeySettingsLabels, PasswordGatedFailure, PasswordProblem, PieSlice, Point, PointValue, PopoverAlign, RadioOption, RegisterFailure, RegisterLabels, ResetPasswordLabels, SaveStatusState, Scale, SearchBarCollapsible, SearchResultCategory, SegmentedControlOption, SegmentedControlSize, SelectOption, SkeletonListLeading, SkeletonVariant, SpinnerSize, StatGridColumns, StatTileTrend, StatTileTrendTone, StepperOrientation, StepperStatus, StepperStep, TableColumn, TimeTicks, TimeUnit, ToastItem, ToastVariant, ToasterPosition, TooltipPoint, TooltipPosition, TooltipRow, TotpEnrollment, TotpQrLabels, TotpQrRenderOptions, TotpQrRenderer, TreeNode, UserChipSize, UsernameProblem, WeekStartsOn };
6599
+ export type { AccordionMode, ActivateFailure, ActivateLabels, AlertAppearance, AlertIconAlign, AlertLive, AlertSize, AlertVariant, Arc, AuthConfig, AuthLabels, AuthPort, AuthPortError, AutocompleteSearchFn, AvatarGroupItem, AvatarSize, AxisSpec, BackupCodesLabels, BackupCodesResult, BadgeAppearance, BadgeSize, BadgeVariant, BandScale, ButtonHaspopup, ButtonSize, ButtonVariant, CalendarDay, CardTone, CardVariant, ChartBox, ChartInterval, ChartMargin, ChartPoint, ChartReader, ChartSeries, CheckboxGroupOption, CheckboxGroupSection, ConfirmDangerModalTone, CopyButtonFeedback, CopyOutcome, CopyStatus, CopyValue, DateInput, DateRangeValue, DescriptionListEntry, DescriptionListLayout, DescriptionListResponsive, DescriptionListValueAlign, DimensionRow, DisclosureAppearance, DisclosureHeadingLevel, DividerOrientation, DrawerEdge, EmailProblem, EmptyStateHeadingLevel, EmptyStateIllustration, EmptyStateSize, EmptyStateTone, EnrolledFactor, FlatTreeNode, FormatBytesOptions, FormatDurationOptions, FormatRelativeTimeOptions, FunnelStep, GbtBytesPipeOptions, GbtDateTimePipeOptions, GbtPipeLocale, GbtRelativeTimePipeOptions, GbtToastKind, GbtToastOptions, IconMarkerAppearance, IconMarkerShape, IconMarkerSize, IconMarkerTone, InputCombobox, JobGraphJob, JobGraphStage, JobGraphStatus, JobStatusValue, LegendEntry, LinearAxisSpec, ListCardState, ListRowTone, ListToolbarAccessors, ListToolbarDirection, ListToolbarSortOption, ListToolbarSortValue, ListToolbarState, ListToolbarStateConfig, LoginLabels, LoginResponse, MenuItemVariant, MfaEnrollmentLabels, MfaFailure, MfaFormOwner, MfaPort, MfaProof, MfaSettingsLabels, MfaSetupResult, MfaStatus, NavTabsOrientation, NotificationDotVariant, PageHeaderLevel, PageLayoutAsidePosition, PageLayoutAsideWidth, PageLayoutWidth, PanelHeadingLevel, Passkey, PasskeyChallenge, PasskeyFailure, PasskeyNameProblem, PasskeySettingsLabels, PasswordGatedFailure, PasswordProblem, PieSlice, Point, PointValue, PopoverAlign, RadioOption, RegisterFailure, RegisterLabels, ResetPasswordLabels, SaveStatusState, Scale, SearchBarCollapsible, SearchResultCategory, SegmentedControlOption, SegmentedControlSize, SelectOption, SkeletonListLeading, SkeletonVariant, SpinnerSize, StatGridColumns, StatTileTrend, StatTileTrendTone, StepperOrientation, StepperStatus, StepperStep, TableColumn, TimeTicks, TimeUnit, ToastItem, ToastVariant, ToasterPosition, TooltipPoint, TooltipPosition, TooltipRow, TotpEnrollment, TotpQrLabels, TotpQrRenderOptions, TotpQrRenderer, TreeNode, UserChipSize, UsernameProblem, WeekStartsOn };