@masmarino/gabarit 2.0.0 → 2.1.1
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.
- package/README.md +131 -85
- package/accordion/README.md +56 -0
- package/alert/README.md +87 -0
- package/app-shell/README.md +133 -0
- package/auth/README.md +155 -0
- package/auth-activate/README.md +119 -0
- package/auth-login/README.md +113 -0
- package/auth-register/README.md +104 -0
- package/auth-reset-password/README.md +120 -0
- package/autocomplete/README.md +77 -0
- package/avatar/README.md +34 -0
- package/avatar-group/README.md +47 -0
- package/badge/README.md +177 -0
- package/bar-chart/README.md +44 -0
- package/breadcrumb/README.md +38 -0
- package/button/README.md +175 -0
- package/card/README.md +179 -0
- package/checkbox/README.md +50 -0
- package/checkbox-group/README.md +78 -0
- package/confirm-danger-modal/README.md +77 -0
- package/copy-button/README.md +90 -0
- package/copy-field/README.md +54 -0
- package/date-picker/README.md +84 -0
- package/description-list/README.md +63 -0
- package/dimension-card/README.md +39 -0
- package/disclosure/README.md +48 -0
- package/divider/README.md +31 -0
- package/drawer/README.md +49 -0
- package/empty-state/README.md +84 -0
- package/fesm2022/masmarino-gabarit-accordion.mjs +243 -0
- package/fesm2022/masmarino-gabarit-accordion.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-alert.mjs +208 -0
- package/fesm2022/masmarino-gabarit-alert.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-app-shell.mjs +378 -0
- package/fesm2022/masmarino-gabarit-app-shell.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-auth-activate.mjs +415 -0
- package/fesm2022/masmarino-gabarit-auth-activate.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-auth-login.mjs +467 -0
- package/fesm2022/masmarino-gabarit-auth-login.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-auth-register.mjs +457 -0
- package/fesm2022/masmarino-gabarit-auth-register.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-auth-reset-password.mjs +364 -0
- package/fesm2022/masmarino-gabarit-auth-reset-password.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-auth.mjs +844 -0
- package/fesm2022/masmarino-gabarit-auth.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-autocomplete.mjs +475 -0
- package/fesm2022/masmarino-gabarit-autocomplete.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-avatar-group.mjs +202 -0
- package/fesm2022/masmarino-gabarit-avatar-group.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-avatar.mjs +107 -0
- package/fesm2022/masmarino-gabarit-avatar.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-badge.mjs +449 -0
- package/fesm2022/masmarino-gabarit-badge.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-bar-chart.mjs +408 -0
- package/fesm2022/masmarino-gabarit-bar-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-breadcrumb.mjs +59 -0
- package/fesm2022/masmarino-gabarit-breadcrumb.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-button.mjs +374 -0
- package/fesm2022/masmarino-gabarit-button.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-card.mjs +400 -0
- package/fesm2022/masmarino-gabarit-card.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-chart.mjs +1289 -0
- package/fesm2022/masmarino-gabarit-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-checkbox-group.mjs +335 -0
- package/fesm2022/masmarino-gabarit-checkbox-group.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-checkbox.mjs +170 -0
- package/fesm2022/masmarino-gabarit-checkbox.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-confirm-danger-modal.mjs +387 -0
- package/fesm2022/masmarino-gabarit-confirm-danger-modal.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-copy-button.mjs +407 -0
- package/fesm2022/masmarino-gabarit-copy-button.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-copy-field.mjs +229 -0
- package/fesm2022/masmarino-gabarit-copy-field.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-date-picker.mjs +1242 -0
- package/fesm2022/masmarino-gabarit-date-picker.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-description-list.mjs +127 -0
- package/fesm2022/masmarino-gabarit-description-list.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-dimension-card.mjs +162 -0
- package/fesm2022/masmarino-gabarit-dimension-card.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-disclosure.mjs +154 -0
- package/fesm2022/masmarino-gabarit-disclosure.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-divider.mjs +90 -0
- package/fesm2022/masmarino-gabarit-divider.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-docs.mjs +16 -2
- package/fesm2022/masmarino-gabarit-docs.mjs.map +1 -1
- package/fesm2022/masmarino-gabarit-drawer.mjs +209 -0
- package/fesm2022/masmarino-gabarit-drawer.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-empty-state.mjs +226 -0
- package/fesm2022/masmarino-gabarit-empty-state.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-file-upload.mjs +335 -0
- package/fesm2022/masmarino-gabarit-file-upload.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-floating-panel.mjs +24 -0
- package/fesm2022/masmarino-gabarit-floating-panel.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-format.mjs +345 -0
- package/fesm2022/masmarino-gabarit-format.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-funnel-chart.mjs +247 -0
- package/fesm2022/masmarino-gabarit-funnel-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-gauge-bar.mjs +180 -0
- package/fesm2022/masmarino-gabarit-gauge-bar.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-git-field.mjs +127 -0
- package/fesm2022/masmarino-gabarit-git-field.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-icon-marker.mjs +150 -0
- package/fesm2022/masmarino-gabarit-icon-marker.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-icon.mjs +308 -0
- package/fesm2022/masmarino-gabarit-icon.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-input.mjs +493 -0
- package/fesm2022/masmarino-gabarit-input.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-job-graph.mjs +216 -0
- package/fesm2022/masmarino-gabarit-job-graph.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-job-status.mjs +104 -0
- package/fesm2022/masmarino-gabarit-job-status.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-line-chart.mjs +574 -0
- package/fesm2022/masmarino-gabarit-line-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-list-card.mjs +320 -0
- package/fesm2022/masmarino-gabarit-list-card.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-list-row.mjs +58 -0
- package/fesm2022/masmarino-gabarit-list-row.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-list-toolbar.mjs +369 -0
- package/fesm2022/masmarino-gabarit-list-toolbar.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-menu.mjs +464 -0
- package/fesm2022/masmarino-gabarit-menu.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-mfa-enrollment.mjs +897 -0
- package/fesm2022/masmarino-gabarit-mfa-enrollment.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-mfa-settings.mjs +629 -0
- package/fesm2022/masmarino-gabarit-mfa-settings.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-modal.mjs +260 -0
- package/fesm2022/masmarino-gabarit-modal.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-nav-tabs.mjs +332 -0
- package/fesm2022/masmarino-gabarit-nav-tabs.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-notification-dot.mjs +119 -0
- package/fesm2022/masmarino-gabarit-notification-dot.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-page-header.mjs +78 -0
- package/fesm2022/masmarino-gabarit-page-header.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-page-layout.mjs +157 -0
- package/fesm2022/masmarino-gabarit-page-layout.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-pagination.mjs +415 -0
- package/fesm2022/masmarino-gabarit-pagination.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-panel.mjs +80 -0
- package/fesm2022/masmarino-gabarit-panel.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-passkey-settings.mjs +606 -0
- package/fesm2022/masmarino-gabarit-passkey-settings.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-pie-chart.mjs +317 -0
- package/fesm2022/masmarino-gabarit-pie-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-popover.mjs +142 -0
- package/fesm2022/masmarino-gabarit-popover.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-radio-group.mjs +202 -0
- package/fesm2022/masmarino-gabarit-radio-group.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-save-status.mjs +142 -0
- package/fesm2022/masmarino-gabarit-save-status.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-search-bar.mjs +576 -0
- package/fesm2022/masmarino-gabarit-search-bar.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-secret-reveal.mjs +348 -0
- package/fesm2022/masmarino-gabarit-secret-reveal.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-segmented-control.mjs +272 -0
- package/fesm2022/masmarino-gabarit-segmented-control.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-select.mjs +512 -0
- package/fesm2022/masmarino-gabarit-select.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-skeleton-list.mjs +189 -0
- package/fesm2022/masmarino-gabarit-skeleton-list.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-skeleton.mjs +109 -0
- package/fesm2022/masmarino-gabarit-skeleton.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-slider.mjs +239 -0
- package/fesm2022/masmarino-gabarit-slider.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-sparkline.mjs +276 -0
- package/fesm2022/masmarino-gabarit-sparkline.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-spinner.mjs +86 -0
- package/fesm2022/masmarino-gabarit-spinner.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-stat-grid.mjs +139 -0
- package/fesm2022/masmarino-gabarit-stat-grid.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-stat-tile.mjs +312 -0
- package/fesm2022/masmarino-gabarit-stat-tile.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-stepper.mjs +219 -0
- package/fesm2022/masmarino-gabarit-stepper.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-switch.mjs +151 -0
- package/fesm2022/masmarino-gabarit-switch.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-table.mjs +206 -0
- package/fesm2022/masmarino-gabarit-table.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-tabs.mjs +210 -0
- package/fesm2022/masmarino-gabarit-tabs.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-tag-input.mjs +288 -0
- package/fesm2022/masmarino-gabarit-tag-input.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-tag.mjs +155 -0
- package/fesm2022/masmarino-gabarit-tag.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-textarea.mjs +369 -0
- package/fesm2022/masmarino-gabarit-textarea.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-timeline-chart.mjs +521 -0
- package/fesm2022/masmarino-gabarit-timeline-chart.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-toaster.mjs +220 -0
- package/fesm2022/masmarino-gabarit-toaster.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-tooltip.mjs +185 -0
- package/fesm2022/masmarino-gabarit-tooltip.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-tree.mjs +258 -0
- package/fesm2022/masmarino-gabarit-tree.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit-user-chip.mjs +106 -0
- package/fesm2022/masmarino-gabarit-user-chip.mjs.map +1 -0
- package/fesm2022/masmarino-gabarit.mjs +83 -24785
- package/fesm2022/masmarino-gabarit.mjs.map +1 -1
- package/file-upload/README.md +47 -0
- package/funnel-chart/README.md +39 -0
- package/gauge-bar/README.md +35 -0
- package/git-field/README.md +34 -0
- package/icon/README.md +52 -0
- package/icon-marker/README.md +37 -0
- package/input/README.md +120 -0
- package/job-graph/README.md +76 -0
- package/job-status/README.md +34 -0
- package/line-chart/README.md +52 -0
- package/list-card/README.md +144 -0
- package/list-row/README.md +72 -0
- package/list-toolbar/README.md +52 -0
- package/menu/README.md +90 -0
- package/mfa-enrollment/README.md +189 -0
- package/mfa-settings/README.md +154 -0
- package/modal/README.md +72 -0
- package/nav-tabs/README.md +106 -0
- package/notification-dot/README.md +43 -0
- package/package.json +329 -1
- package/page-header/README.md +56 -0
- package/page-layout/README.md +76 -0
- package/pagination/README.md +73 -0
- package/panel/README.md +56 -0
- package/passkey-settings/README.md +120 -0
- package/pie-chart/README.md +85 -0
- package/popover/README.md +62 -0
- package/radio-group/README.md +47 -0
- package/save-status/README.md +44 -0
- package/search-bar/README.md +84 -0
- package/secret-reveal/README.md +60 -0
- package/segmented-control/README.md +79 -0
- package/select/README.md +61 -0
- package/skeleton/README.md +49 -0
- package/skeleton-list/README.md +40 -0
- package/slider/README.md +44 -0
- package/sparkline/README.md +37 -0
- package/spinner/README.md +41 -0
- package/stat-grid/README.md +47 -0
- package/stat-tile/README.md +75 -0
- package/stepper/README.md +67 -0
- package/switch/README.md +51 -0
- package/table/README.md +75 -0
- package/tabs/README.md +34 -0
- package/tag/README.md +34 -0
- package/tag-input/README.md +45 -0
- package/textarea/README.md +76 -0
- package/timeline-chart/README.md +49 -0
- package/toaster/README.md +92 -0
- package/tooltip/README.md +50 -0
- package/tree/README.md +79 -0
- package/types/masmarino-gabarit-accordion.d.ts +54 -0
- package/types/masmarino-gabarit-alert.d.ts +65 -0
- package/types/masmarino-gabarit-app-shell.d.ts +102 -0
- package/types/masmarino-gabarit-auth-activate.d.ts +70 -0
- package/types/masmarino-gabarit-auth-login.d.ts +63 -0
- package/types/masmarino-gabarit-auth-register.d.ts +66 -0
- package/types/masmarino-gabarit-auth-reset-password.d.ts +53 -0
- package/types/masmarino-gabarit-auth.d.ts +543 -0
- package/types/masmarino-gabarit-autocomplete.d.ts +140 -0
- package/types/masmarino-gabarit-avatar-group.d.ts +60 -0
- package/types/masmarino-gabarit-avatar.d.ts +31 -0
- package/types/masmarino-gabarit-badge.d.ts +139 -0
- package/types/masmarino-gabarit-bar-chart.d.ts +111 -0
- package/types/masmarino-gabarit-breadcrumb.d.ts +12 -0
- package/types/masmarino-gabarit-button.d.ts +108 -0
- package/types/masmarino-gabarit-card.d.ts +102 -0
- package/types/masmarino-gabarit-chart.d.ts +361 -0
- package/types/masmarino-gabarit-checkbox-group.d.ts +113 -0
- package/types/masmarino-gabarit-checkbox.d.ts +49 -0
- package/types/masmarino-gabarit-confirm-danger-modal.d.ts +94 -0
- package/types/masmarino-gabarit-copy-button.d.ts +111 -0
- package/types/masmarino-gabarit-copy-field.d.ts +64 -0
- package/types/masmarino-gabarit-date-picker.d.ts +399 -0
- package/types/masmarino-gabarit-description-list.d.ts +40 -0
- package/types/masmarino-gabarit-dimension-card.d.ts +55 -0
- package/types/masmarino-gabarit-disclosure.d.ts +44 -0
- package/types/masmarino-gabarit-divider.d.ts +20 -0
- package/types/masmarino-gabarit-docs.d.ts +2 -1
- package/types/masmarino-gabarit-drawer.d.ts +51 -0
- package/types/masmarino-gabarit-empty-state.d.ts +67 -0
- package/types/masmarino-gabarit-file-upload.d.ts +95 -0
- package/types/masmarino-gabarit-floating-panel.d.ts +14 -0
- package/types/masmarino-gabarit-format.d.ts +54 -0
- package/types/masmarino-gabarit-funnel-chart.d.ts +78 -0
- package/types/masmarino-gabarit-gauge-bar.d.ts +54 -0
- package/types/masmarino-gabarit-git-field.d.ts +39 -0
- package/types/masmarino-gabarit-icon-marker.d.ts +47 -0
- package/types/masmarino-gabarit-icon.d.ts +23 -0
- package/types/masmarino-gabarit-input.d.ts +181 -0
- package/types/masmarino-gabarit-job-graph.d.ts +63 -0
- package/types/masmarino-gabarit-job-status.d.ts +20 -0
- package/types/masmarino-gabarit-line-chart.d.ts +153 -0
- package/types/masmarino-gabarit-list-card.d.ts +87 -0
- package/types/masmarino-gabarit-list-row.d.ts +14 -0
- package/types/masmarino-gabarit-list-toolbar.d.ts +100 -0
- package/types/masmarino-gabarit-menu.d.ts +93 -0
- package/types/masmarino-gabarit-mfa-enrollment.d.ts +142 -0
- package/types/masmarino-gabarit-mfa-settings.d.ts +89 -0
- package/types/masmarino-gabarit-modal.d.ts +60 -0
- package/types/masmarino-gabarit-nav-tabs.d.ts +65 -0
- package/types/masmarino-gabarit-notification-dot.d.ts +34 -0
- package/types/masmarino-gabarit-page-header.d.ts +20 -0
- package/types/masmarino-gabarit-page-layout.d.ts +46 -0
- package/types/masmarino-gabarit-pagination.d.ts +109 -0
- package/types/masmarino-gabarit-panel.d.ts +21 -0
- package/types/masmarino-gabarit-passkey-settings.d.ts +94 -0
- package/types/masmarino-gabarit-pie-chart.d.ts +94 -0
- package/types/masmarino-gabarit-popover.d.ts +33 -0
- package/types/masmarino-gabarit-radio-group.d.ts +66 -0
- package/types/masmarino-gabarit-save-status.d.ts +39 -0
- package/types/masmarino-gabarit-search-bar.d.ts +183 -0
- package/types/masmarino-gabarit-secret-reveal.d.ts +95 -0
- package/types/masmarino-gabarit-segmented-control.d.ts +76 -0
- package/types/masmarino-gabarit-select.d.ts +146 -0
- package/types/masmarino-gabarit-skeleton-list.d.ts +54 -0
- package/types/masmarino-gabarit-skeleton.d.ts +26 -0
- package/types/masmarino-gabarit-slider.d.ts +73 -0
- package/types/masmarino-gabarit-sparkline.d.ts +70 -0
- package/types/masmarino-gabarit-spinner.d.ts +20 -0
- package/types/masmarino-gabarit-stat-grid.d.ts +39 -0
- package/types/masmarino-gabarit-stat-tile.d.ts +79 -0
- package/types/masmarino-gabarit-stepper.d.ts +67 -0
- package/types/masmarino-gabarit-switch.d.ts +42 -0
- package/types/masmarino-gabarit-table.d.ts +60 -0
- package/types/masmarino-gabarit-tabs.d.ts +40 -0
- package/types/masmarino-gabarit-tag-input.d.ts +78 -0
- package/types/masmarino-gabarit-tag.d.ts +35 -0
- package/types/masmarino-gabarit-textarea.d.ts +109 -0
- package/types/masmarino-gabarit-timeline-chart.d.ts +145 -0
- package/types/masmarino-gabarit-toaster.d.ts +62 -0
- package/types/masmarino-gabarit-tooltip.d.ts +39 -0
- package/types/masmarino-gabarit-tree.d.ts +71 -0
- package/types/masmarino-gabarit-user-chip.d.ts +26 -0
- package/types/masmarino-gabarit.d.ts +83 -6599
- package/user-chip/README.md +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masmarino-gabarit-auth.mjs","names":[],"sources":["../../../projects/gabarit/auth/auth-footer/auth-footer.ts","../../../projects/gabarit/auth/auth-footer/auth-footer.html","../../../projects/gabarit/auth/auth-labels.ts","../../../projects/gabarit/auth/auth-panel/auth-panel.ts","../../../projects/gabarit/auth/auth-panel/auth-panel.html","../../../projects/gabarit/auth/ports/auth.port.ts","../../../projects/gabarit/auth/ports/mfa.port.ts","../../../projects/gabarit/auth/shared/port-error.ts","../../../projects/gabarit/auth/shared/account-errors.ts","../../../projects/gabarit/auth/shared/account-rules.ts","../../../projects/gabarit/auth/shared/activation-link.ts","../../../projects/gabarit/auth/shared/focus-after-render.ts","../../../projects/gabarit/auth/shared/mfa-errors.ts","../../../projects/gabarit/auth/shared/mfa-settings-state.ts","../../../projects/gabarit/auth/shared/passkey-name.ts","../../../projects/gabarit/auth/webauthn.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, Directive, input } from '@angular/core'\nimport { Button } from '@masmarino/gabarit/button'\n\n@Directive({\n selector: '[gbtAuthFooterLink]',\n standalone: true,\n host: { class: 'gbt-auth-footer__link' },\n})\nexport class AuthFooterLink {}\n\n@Component({\n selector: 'gbt-auth-footer',\n standalone: true,\n imports: [Button],\n templateUrl: './auth-footer.html',\n styleUrl: './auth-footer.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AuthFooter {\n text = input.required<string>()\n href = input<string | null>(null)\n linkText = input('')\n}\n","<p class=\"gbt-auth-footer\">\n <span>{{ text() }}</span>\n @if (href(); as url) {\n <a gbtButton class=\"gbt-auth-footer__link\" variant=\"link\" [href]=\"url\">{{ linkText() }}</a>\n }\n <ng-content />\n</p>\n","import { InjectionToken, type Provider, computed, inject, type Signal } from '@angular/core'\n\nexport type EnrolledFactor = 'totp' | 'passkey'\n\nexport interface TotpQrLabels {\n fallback: string\n imageAlt: string\n secretLabel: string\n fallbackSecretLabel: string\n copyLabel: string\n copied: string\n copyFailed: string\n}\n\nexport const DEFAULT_TOTP_QR_LABELS: Readonly<TotpQrLabels> = Object.freeze<TotpQrLabels>({\n fallback: 'The QR code could not be displayed: enter the key below in your app.',\n imageAlt: 'QR code to scan with your authenticator app',\n secretLabel: 'Or enter this key in your app',\n fallbackSecretLabel: 'Setup key',\n copyLabel: 'Copy the setup key',\n copied: 'Copied',\n copyFailed: 'Copy failed, key selected',\n})\n\nexport interface BackupCodesLabels {\n listLabel: string\n copy: string\n copied: string\n copyFailed: string\n download: string\n acknowledge: string\n fileName: string\n fileTitle: string\n fileNotice: string\n}\n\nexport const DEFAULT_BACKUP_CODES_LABELS: Readonly<BackupCodesLabels> =\n Object.freeze<BackupCodesLabels>({\n listLabel: 'Backup codes',\n copy: 'Copy codes',\n copied: 'Codes copied',\n copyFailed: 'Copy failed, codes selected',\n download: 'Download',\n acknowledge: 'I have saved my backup codes',\n fileName: 'backup-codes.txt',\n fileTitle: 'Backup codes',\n fileNotice: 'Each code can only be used once. Keep them somewhere safe.',\n })\n\ninterface CommonFailureLabels {\n tooManyAttempts: string\n}\n\nexport interface MfaEnrollmentLabels extends CommonFailureLabels {\n step: (current: number, total: number) => string\n choiceHeading: string\n scanHeading: string\n passkeyHeading: string\n codesHeading: string\n mandatory: string\n choiceLead: string\n passkeyOption: string\n recommended: string\n passkeyOptionText: string\n usePasskey: string\n appOption: string\n appOptionText: string\n useApp: string\n preparing: string\n back: string\n todoInstall: string\n todoScan: string\n todoKeep: string\n begin: string\n scanLead: string\n codeLabel: string\n activate: string\n verifying: string\n passkeyLead: string\n passkeyNameLabel: string\n defaultPasskeyName: string\n createPasskey: string\n creating: string\n promptOpen: string\n codesLead: (factor: EnrolledFactor) => string\n continue: string\n enterCode: string\n wrongCode: string\n startFailed: string\n activationFailed: string\n passkeyFailed: string\n alreadyRegistered: string\n cancelled: string\n browserUnsupported: string\n passkeysUnavailable: string\n loginExpired: string\n alreadySetUp: string\n nameTooLong: (max: number) => string\n nameControlCharacters: string\n}\n\nexport const DEFAULT_MFA_ENROLLMENT_LABELS: Readonly<MfaEnrollmentLabels> =\n Object.freeze<MfaEnrollmentLabels>({\n step: (current, total) => `Step ${current} of ${total}`,\n choiceHeading: 'Protect your account',\n scanHeading: 'Set up your app',\n passkeyHeading: 'Create your passkey',\n codesHeading: 'Save your backup codes',\n mandatory: 'Two-factor authentication is required to secure your account.',\n choiceLead: 'Choose how you will confirm your identity each time you sign in.',\n passkeyOption: 'Passkey',\n recommended: 'Recommended',\n passkeyOptionText:\n 'Touch ID, Windows Hello, a PIN or a security key: nothing to type, and impossible to phish.',\n usePasskey: 'Use a passkey',\n appOption: 'Authenticator app',\n appOptionText:\n 'Google Authenticator, Authy, 1Password…: a 6-digit code to type each time you sign in.',\n useApp: 'Use an app',\n preparing: 'Preparing',\n back: 'Back',\n todoInstall: 'Install an authenticator app (Google Authenticator, Authy, 1Password…).',\n todoScan: 'Scan the QR code shown at the next step and enter the 6-digit code.',\n todoKeep: 'Keep your backup codes: they will get you in if you lose your phone.',\n begin: 'Get started',\n scanLead:\n 'Scan this QR code with your authenticator app, then enter the 6-digit code it shows.',\n codeLabel: '6-digit code',\n activate: 'Activate',\n verifying: 'Verifying',\n passkeyLead:\n 'Give this key a name to recognise it later, then confirm with your device: Touch ID, Windows Hello, PIN or security key.',\n passkeyNameLabel: 'Key name (optional)',\n defaultPasskeyName: 'Passkey',\n createPasskey: 'Create the passkey',\n creating: 'Creating',\n promptOpen: 'Confirm on your device to create the key.',\n codesLead: (factor) =>\n `Two-factor authentication is on. These codes will not be shown again: they let you sign in if you lose access to ${factor === 'passkey' ? 'your passkey' : 'your app'}, and each one works only once.`,\n continue: 'Continue',\n enterCode: 'Enter the 6-digit code from your app',\n wrongCode: 'Incorrect code',\n startFailed: 'The setup could not start, try again.',\n activationFailed: 'Activation failed, try again.',\n passkeyFailed: 'The passkey could not be created, try again.',\n alreadyRegistered: 'This key is already registered',\n cancelled: 'Operation cancelled',\n browserUnsupported: 'This browser does not support passkeys.',\n passkeysUnavailable: 'Passkeys are not available on this server.',\n loginExpired: 'Your sign-in has expired, sign in again.',\n alreadySetUp: 'Two-factor authentication is already set up, sign in again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n nameTooLong: (max) => `The name must not be longer than ${max} characters`,\n nameControlCharacters: 'The name cannot contain control characters',\n })\n\nexport interface LoginLabels extends CommonFailureLabels {\n heading: string\n intro: string\n challengeHeading: string\n enrollmentHeading: string\n username: string\n password: string\n showPassword: string\n hidePassword: string\n submit: string\n submitting: string\n registerPrompt: string\n wrongCredentials: string\n loginFailed: string\n introBackupCode: string\n introPasskeyOrCode: string\n introPasskey: string\n introCode: string\n blockedByServer: string\n blockedByBrowser: string\n backToPasskeyOrApp: string\n backToPasskey: string\n backToApp: string\n useBackupCode: string\n back: string\n backupCodeLabel: string\n codeLabel: string\n verify: string\n verifying: string\n usePasskey: string\n passkeyValidating: string\n or: string\n passkeyPrompt: string\n enterBackupCode: string\n enterCode: string\n wrongCode: string\n verifyFailed: string\n cancelled: string\n browserUnsupported: string\n passkeyRefused: string\n passkeysUnavailable: string\n loginExpired: string\n}\n\nexport const DEFAULT_LOGIN_LABELS: Readonly<LoginLabels> = Object.freeze<LoginLabels>({\n heading: 'Sign in',\n intro: 'Sign in to pick up where you left off.',\n challengeHeading: 'Two-step verification',\n enrollmentHeading: 'Two-factor authentication',\n username: 'Username',\n password: 'Password',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n submit: 'Sign in',\n submitting: 'Signing in',\n registerPrompt: 'No account yet?',\n wrongCredentials: 'Incorrect username or password',\n loginFailed: 'Sign-in failed, try again.',\n introBackupCode: 'Enter one of your backup codes. Each code works only once.',\n introPasskeyOrCode: 'Use your passkey, or enter the 6-digit code from your app.',\n introPasskey:\n 'Confirm it is really you with your passkey: fingerprint, face, device PIN or security key.',\n introCode: 'Enter the 6-digit code shown by your authenticator app.',\n blockedByServer: 'Passkeys are not available on this server. Use a backup code.',\n blockedByBrowser: 'This browser does not support passkeys. Use a backup code.',\n backToPasskeyOrApp: 'Use my passkey or my app',\n backToPasskey: 'Use my passkey',\n backToApp: 'Use the code from my app',\n useBackupCode: 'Use a backup code',\n back: 'Back',\n backupCodeLabel: 'Backup code',\n codeLabel: '6-digit code',\n verify: 'Verify',\n verifying: 'Verifying',\n usePasskey: 'Use a passkey',\n passkeyValidating: 'Waiting for your device',\n or: 'or',\n passkeyPrompt: 'Confirm on your device to sign in.',\n enterBackupCode: 'Enter a backup code',\n enterCode: 'Enter the 6-digit code from your app',\n wrongCode: 'Incorrect code',\n verifyFailed: 'Verification failed, try again.',\n cancelled: 'Operation cancelled',\n browserUnsupported: 'This browser does not support passkeys.',\n passkeyRefused: 'Passkey refused',\n passkeysUnavailable: 'Passkeys are not available on this server.',\n loginExpired: 'Your sign-in has expired, sign in again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n})\n\nexport interface RegisterLabels extends CommonFailureLabels {\n heading: string\n intro: string\n enrollmentHeading: string\n loading: string\n closedHeading: string\n closedMessage: string\n signIn: string\n createdHeading: string\n createdMessage: string\n enrollmentExpired: string\n createdName: string\n username: string\n usernameHint: string\n email: string\n password: string\n passwordHint: (minLength: number) => string\n showPassword: string\n hidePassword: string\n submit: string\n submitting: string\n signInPrompt: string\n usernameEmpty: string\n usernameInvalid: string\n emailEmpty: string\n emailInvalid: string\n passwordEmpty: string\n passwordTooShort: (minLength: number) => string\n invalid: string\n reserved: string\n taken: string\n failed: string\n}\n\nexport const DEFAULT_REGISTER_LABELS: Readonly<RegisterLabels> = Object.freeze<RegisterLabels>({\n heading: 'Create an account',\n intro: 'Create your account to get started.',\n enrollmentHeading: 'Two-factor authentication',\n loading: 'Loading',\n closedHeading: 'Registration is closed',\n closedMessage:\n 'This instance does not accept open registration. Ask an administrator for an invitation: you will receive a link by email to activate your account.',\n signIn: 'Sign in',\n createdHeading: 'Your account has been created',\n createdMessage:\n 'Sign in with your password to finish setting up two-factor authentication, required before you start.',\n enrollmentExpired: 'The setup has expired. ',\n createdName: 'Your username:',\n username: 'Username',\n usernameHint: '3 to 32 characters: letters, digits, - and _. Saved in lower case.',\n email: 'Email address',\n password: 'Password',\n passwordHint: (minLength) => `At least ${minLength} characters.`,\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n submit: 'Create my account',\n submitting: 'Creating the account',\n signInPrompt: 'Already have an account?',\n usernameEmpty: 'Enter a username',\n usernameInvalid: 'Start with a letter; 3 to 32 characters: letters, digits, - and _',\n emailEmpty: 'Enter your email address',\n emailInvalid: 'Enter a valid email address, for example name@example.com',\n passwordEmpty: 'Enter a password',\n passwordTooShort: (minLength) => `At least ${minLength} characters`,\n invalid: 'Check the fields',\n reserved: 'This username is not available',\n taken: 'This username or email address is already in use',\n failed: 'The account could not be created, try again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n})\n\nexport interface ActivateLabels extends CommonFailureLabels {\n heading: string\n intro: string\n /** The intro when the invitee chooses their username too (`chooseUsername`). */\n introWithUsername: string\n username: string\n usernameHint: string\n usernameEmpty: string\n usernameInvalid: string\n usernameReserved: string\n usernameTaken: string\n password: string\n passwordHint: (minLength: number) => string\n confirmation: string\n showPassword: string\n hidePassword: string\n submit: string\n submitting: string\n signInPrompt: string\n successHeading: string\n successMessage: string\n invalidHeading: string\n invalidMessage: string\n signIn: string\n passwordEmpty: string\n passwordTooShort: (minLength: number) => string\n confirmationEmpty: string\n mismatch: string\n weakPassword: (minLength: number) => string\n failed: string\n}\n\nexport const DEFAULT_ACTIVATE_LABELS: Readonly<ActivateLabels> = Object.freeze<ActivateLabels>({\n heading: 'Activate your account',\n intro:\n 'Choose the password of your account. Two-factor authentication will be set up the first time you sign in.',\n introWithUsername:\n 'Choose the username and the password of your account. Two-factor authentication will be set up the first time you sign in.',\n username: 'Username',\n usernameHint: '3 to 32 characters: letters, digits, - and _. Saved in lower case.',\n usernameEmpty: 'Enter a username',\n usernameInvalid: 'Start with a letter; 3 to 32 characters: letters, digits, - and _',\n usernameReserved: 'This username is not available',\n usernameTaken: 'This username is already in use',\n password: 'New password',\n passwordHint: (minLength) => `At least ${minLength} characters.`,\n confirmation: 'Confirm the password',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n submit: 'Activate my account',\n submitting: 'Activating',\n signInPrompt: 'Is your account already active?',\n successHeading: 'Your account is activated',\n successMessage:\n 'You can now sign in. We will then guide you through protecting your account with two-factor authentication.',\n invalidHeading: 'This link does not work',\n invalidMessage:\n 'This invitation link is invalid or has expired. Ask an administrator to send you a new one.',\n signIn: 'Sign in',\n passwordEmpty: 'Enter a password',\n passwordTooShort: (minLength) => `At least ${minLength} characters`,\n confirmationEmpty: 'Confirm your password',\n mismatch: 'The passwords do not match',\n weakPassword: (minLength) => `The password must be at least ${minLength} characters long`,\n failed: 'Activation failed, try again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n})\n\nexport interface ResetPasswordLabels extends CommonFailureLabels {\n heading: string\n intro: string\n password: string\n passwordHint: (minLength: number) => string\n confirmation: string\n showPassword: string\n hidePassword: string\n submit: string\n submitting: string\n signInPrompt: string\n successHeading: string\n successMessage: string\n invalidHeading: string\n invalidMessage: string\n signIn: string\n passwordEmpty: string\n passwordTooShort: (minLength: number) => string\n confirmationEmpty: string\n mismatch: string\n weakPassword: (minLength: number) => string\n failed: string\n}\n\nexport const DEFAULT_RESET_PASSWORD_LABELS: Readonly<ResetPasswordLabels> =\n Object.freeze<ResetPasswordLabels>({\n heading: 'Choose a new password',\n intro:\n 'An administrator has reset the password of your account. Choose a new one to sign in again.',\n password: 'New password',\n passwordHint: (minLength) => `At least ${minLength} characters.`,\n confirmation: 'Confirm the new password',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n submit: 'Set new password',\n submitting: 'Setting the password',\n signInPrompt: 'Already set your new password?',\n successHeading: 'Your password has been changed',\n successMessage: 'You can now sign in with your new password.',\n invalidHeading: 'This link does not work',\n invalidMessage:\n 'This password reset link is invalid or has expired. Ask an administrator to send you a new one.',\n signIn: 'Sign in',\n passwordEmpty: 'Enter a new password',\n passwordTooShort: (minLength) => `At least ${minLength} characters`,\n confirmationEmpty: 'Confirm your new password',\n mismatch: 'The passwords do not match',\n weakPassword: (minLength) => `The password must be at least ${minLength} characters long`,\n failed: 'The new password could not be set, try again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n })\n\nexport interface MfaSettingsLabels extends CommonFailureLabels {\n heading: string\n enrollingHeading: string\n codesHeading: string\n help: string\n codesHelp: string\n loading: string\n loadFailed: string\n retry: string\n enrollLead: string\n enrollSubmit: string\n enrollBusy: string\n enrollFailed: string\n regenerateLead: string\n regenerateSubmit: string\n regenerateBusy: string\n regenerateFailed: string\n disableSubmit: string\n disableCheckBusy: string\n disableFailed: string\n removeTitle: string\n removeHelp: string\n removeAction: string\n removeDialogHeading: string\n removeDialogMessage: string\n removePromptLead: string\n removeBusy: string\n resetTitle: string\n resetHelp: string\n resetAction: string\n resetDialogHeading: string\n resetDialogMessage: string\n resetPromptLead: string\n resetBusy: string\n codesLeft: (count: number) => string\n lowCodes: string\n scanLead: string\n codeLabel: string\n activate: string\n verifying: string\n cancel: string\n close: string\n codesLeadEnrolled: string\n codesLeadRegenerated: string\n dontLeave: string\n done: string\n appConfigured: string\n enabled: string\n appHelpWithPasskey: string\n appHelp: string\n noApp: string\n optional: string\n noAppHelp: string\n addApp: string\n backupCodesTitle: string\n backupCodesHelp: string\n regenerateCodes: string\n noFactorWarning: string\n setUpNow: string\n currentPassword: string\n showPassword: string\n hidePassword: string\n enterPassword: string\n wrongPassword: string\n enterCode: string\n wrongCode: string\n activationFailed: string\n signedOut: string\n}\n\nexport const DEFAULT_MFA_SETTINGS_LABELS: Readonly<MfaSettingsLabels> =\n Object.freeze<MfaSettingsLabels>({\n heading: 'Authenticator app',\n enrollingHeading: 'Set up the authenticator app',\n codesHeading: 'Backup codes',\n help: 'Google Authenticator, Authy, 1Password…: any TOTP app works.',\n codesHelp: 'Keep them: they are shown only once.',\n loading: 'Loading two-factor authentication…',\n loadFailed: 'Two-factor authentication could not be loaded.',\n retry: 'Retry',\n enrollLead: 'Confirm your password to start the setup.',\n enrollSubmit: 'Continue',\n enrollBusy: 'Preparing',\n enrollFailed: 'The setup could not start, try again.',\n regenerateLead:\n 'Confirm your password to generate 10 new codes. The old ones stop working right away.',\n regenerateSubmit: 'Regenerate',\n regenerateBusy: 'Regenerating',\n regenerateFailed: 'The backup codes could not be regenerated, try again.',\n disableSubmit: 'Continue',\n disableCheckBusy: 'Checking',\n disableFailed: 'Two-factor authentication could not be reset, try again.',\n removeTitle: 'Remove the authenticator app',\n removeHelp:\n 'Removes your current app. You will be signed out of all your devices and will sign in again with your passkey.',\n removeAction: 'Remove',\n removeDialogHeading: 'Remove the authenticator app?',\n removeDialogMessage:\n 'You will be signed out of all your devices. You will sign in again with your passkey, without an app.',\n removePromptLead: 'Confirm your password to remove your authenticator app.',\n removeBusy: 'Removing',\n resetTitle: 'Reset two-factor authentication',\n resetHelp:\n 'Removes your current app. You will be signed out of all your devices and will have to set up a new one the next time you sign in.',\n resetAction: 'Reset',\n resetDialogHeading: 'Reset two-factor authentication?',\n resetDialogMessage:\n 'You will be signed out and will have to set up a new authenticator app the next time you sign in.',\n resetPromptLead: 'Confirm your password to reset two-factor authentication.',\n resetBusy: 'Resetting',\n codesLeft: (count) =>\n count === 0\n ? 'No backup codes left'\n : count === 1\n ? '1 backup code left'\n : `${count} backup codes left`,\n lowCodes: 'Regenerate some so that you do not lose access to your account.',\n scanLead:\n 'Scan this QR code with your authenticator app, then enter the 6-digit code it shows.',\n codeLabel: '6-digit code',\n activate: 'Activate',\n verifying: 'Verifying',\n cancel: 'Cancel',\n close: 'Close',\n codesLeadEnrolled:\n 'Two-factor authentication is on. These codes will not be shown again: they let you sign in if you lose access to your app, and each one works only once.',\n codesLeadRegenerated:\n 'Here are your new backup codes. The old codes no longer work. These codes will not be shown again, and each one works only once.',\n dontLeave: 'Do not leave this page before you have saved them.',\n done: 'Done',\n appConfigured: 'App configured',\n enabled: 'On',\n appHelpWithPasskey:\n 'A 6-digit code, generated by your app, can replace your passkey after your password.',\n appHelp: 'A 6-digit code, generated by your app, is asked after your password.',\n noApp: 'No app configured',\n optional: 'Optional',\n noAppHelp:\n 'Your passkey is enough to sign in. Add an app for a second way in: it generates a 6-digit code.',\n addApp: 'Add an app',\n backupCodesTitle: 'Backup codes',\n backupCodesHelp:\n 'Each code works only once. Generating new ones invalidates the previous ones.',\n regenerateCodes: 'Regenerate backup codes',\n noFactorWarning:\n 'Two-factor authentication is required: you will have to set it up the next time you sign in.',\n setUpNow: 'Set up now',\n currentPassword: 'Current password',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n enterPassword: 'Enter your password',\n wrongPassword: 'Incorrect password',\n enterCode: 'Enter the 6-digit code from your app',\n wrongCode: 'Incorrect code',\n activationFailed: 'Activation failed, try again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n signedOut: 'You have been signed out. Sign in again to continue.',\n })\n\nexport interface PasskeySettingsLabels extends CommonFailureLabels {\n heading: string\n description: string\n loading: string\n loadFailed: string\n retry: string\n browserBlocked: string\n serverBlocked: string\n emptyHeading: string\n emptyMessage: string\n listLabel: string\n added: (absolute: boolean) => string\n lastUsed: (absolute: boolean) => string\n neverUsed: string\n delete: string\n deleteKey: (name: string) => string\n passkeyAdded: (name: string) => string\n passkeyGone: (name: string) => string\n addPasskey: string\n finishAppFirst: string\n deleteDialogHeading: string\n deleteDialogMessage: (name: string, lastFactor: boolean) => string\n deleteConfirm: string\n cancel: string\n close: string\n deleting: string\n addLead: string\n promptOpen: string\n nameLabel: string\n defaultPasskeyName: string\n currentPassword: string\n showPassword: string\n hidePassword: string\n create: string\n creating: string\n deleteLead: (name: string) => string\n lastFactorWarning: string\n continue: string\n checking: string\n nameTooLong: (max: number) => string\n nameControlCharacters: string\n enterPassword: string\n wrongPassword: string\n tooManyPasskeys: string\n alreadyRegistered: string\n passkeysUnavailable: string\n addFailed: string\n cancelled: string\n browserUnsupported: string\n deleteFailed: string\n signedOut: string\n}\n\nconst LAST_FACTOR =\n 'This is your last factor: you will have to set up a new one the next time you sign in.'\n\nexport const DEFAULT_PASSKEY_SETTINGS_LABELS: Readonly<PasskeySettingsLabels> =\n Object.freeze<PasskeySettingsLabels>({\n heading: 'Passkeys',\n description:\n 'Confirm your sign-in with your fingerprint, your face or the PIN of your device, or with a security key.',\n loading: 'Loading passkeys…',\n loadFailed: 'Passkeys could not be loaded.',\n retry: 'Retry',\n browserBlocked:\n 'This browser does not support passkeys: you cannot add one here, but you can delete the ones you already have.',\n serverBlocked:\n 'Passkeys are not available on this server. You cannot add one, but you can delete the ones you already have.',\n emptyHeading: 'No passkeys',\n emptyMessage: 'Add one to confirm your sign-in with a gesture, without a code to copy.',\n listLabel: 'Registered passkeys',\n added: (absolute) => (absolute ? 'Added on' : 'Added'),\n lastUsed: (absolute) => (absolute ? 'Last used on' : 'Last used'),\n neverUsed: 'Never used',\n delete: 'Delete',\n deleteKey: (name) => `Delete the key ${name}`,\n passkeyAdded: (name) => `Passkey “${name}” added.`,\n passkeyGone: (name) => `The passkey “${name}” no longer exists.`,\n addPasskey: 'Add a passkey',\n finishAppFirst: 'Finish setting up the authenticator app first.',\n deleteDialogHeading: 'Delete this passkey?',\n deleteDialogMessage: (name, lastFactor) =>\n `“${name}” will no longer let you sign in. You will be signed out of all your devices and will have to sign in again.` +\n (lastFactor ? ` ${LAST_FACTOR}` : ''),\n deleteConfirm: 'Delete',\n cancel: 'Cancel',\n close: 'Close',\n deleting: 'Deleting',\n addLead: 'Name this key and confirm your password: your device will then ask you to confirm.',\n promptOpen: 'Confirm on your device to create the key.',\n nameLabel: 'Key name (optional)',\n defaultPasskeyName: 'Passkey',\n currentPassword: 'Current password',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n create: 'Create the passkey',\n creating: 'Creating',\n deleteLead: (name) => `Confirm your password to delete “${name}”.`,\n lastFactorWarning: LAST_FACTOR,\n continue: 'Continue',\n checking: 'Checking',\n nameTooLong: (max) => `The name must not be longer than ${max} characters`,\n nameControlCharacters: 'The name cannot contain control characters',\n enterPassword: 'Enter your password',\n wrongPassword: 'Incorrect password',\n tooManyPasskeys:\n 'You have reached the maximum number of passkeys: delete one before adding another.',\n alreadyRegistered: 'This key is already registered',\n passkeysUnavailable: 'Passkeys are not available on this server.',\n addFailed: 'The passkey could not be created, try again.',\n cancelled: 'Operation cancelled',\n browserUnsupported: 'This browser does not support passkeys.',\n deleteFailed: 'The passkey could not be deleted, try again.',\n tooManyAttempts: 'Too many attempts, try again in a few minutes',\n signedOut: 'You have been signed out. Sign in again to continue.',\n })\n\nexport interface AuthLabels {\n totpQr?: Partial<TotpQrLabels>\n backupCodes?: Partial<BackupCodesLabels>\n mfaEnrollment?: Partial<MfaEnrollmentLabels>\n login?: Partial<LoginLabels>\n register?: Partial<RegisterLabels>\n activate?: Partial<ActivateLabels>\n resetPassword?: Partial<ResetPasswordLabels>\n mfaSettings?: Partial<MfaSettingsLabels>\n passkeySettings?: Partial<PasskeySettingsLabels>\n}\n\nexport const AUTH_LABELS = new InjectionToken<AuthLabels>('AUTH_LABELS')\n\nexport function provideAuthLabels(labels: AuthLabels): Provider {\n return { provide: AUTH_LABELS, useValue: labels }\n}\n\nexport function authLabels<K extends keyof AuthLabels, T extends object>(\n part: K,\n defaults: T,\n own: Signal<Partial<T>>,\n): Signal<T> {\n const provided = inject(AUTH_LABELS, { optional: true })?.[part] as Partial<T> | undefined\n return computed(() => ({ ...defaults, ...defined(provided), ...defined(own()) }))\n}\n\nfunction defined<T extends object>(partial: Partial<T> | undefined): Partial<T> {\n if (!partial) {\n return {}\n }\n return Object.fromEntries(\n Object.entries(partial).filter(([, value]) => value !== undefined),\n ) as Partial<T>\n}\n","import { ChangeDetectionStrategy, Component, booleanAttribute, input } from '@angular/core'\n\n@Component({\n selector: 'gbt-auth-panel',\n standalone: true,\n templateUrl: './auth-panel.html',\n styleUrl: './auth-panel.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AuthPanel {\n heading = input('')\n intro = input('')\n wide = input(false, { transform: booleanAttribute })\n}\n","<main class=\"gbt-auth-panel\">\n <ng-content select=\"[auth-backdrop]\" />\n <div class=\"gbt-auth-panel__panel\" [class.gbt-auth-panel__panel--wide]=\"wide()\">\n <div class=\"gbt-auth-panel__logo\"><ng-content select=\"[auth-logo]\" /></div>\n\n @if (heading()) {\n <h1\n class=\"gbt-auth-panel__heading\"\n [class.gbt-auth-panel__heading--alone]=\"!intro()\"\n tabindex=\"-1\"\n >\n {{ heading() }}\n </h1>\n @if (intro()) {\n <p class=\"gbt-auth-panel__intro\">{{ intro() }}</p>\n }\n }\n\n <ng-content />\n </div>\n</main>\n","import { InjectionToken } from '@angular/core'\nimport type { Observable } from 'rxjs'\n\nexport interface LoginResponse {\n token: string | null\n mfaToken?: string\n mfaSetupRequired?: boolean\n mfaHasTotp?: boolean\n mfaHasPasskey?: boolean\n}\n\nexport interface AuthConfig {\n registrationEnabled: boolean\n passkeysAvailable: boolean\n}\n\nexport interface PasskeyChallenge {\n challengeId: string\n publicKey: unknown\n}\n\nexport type MfaProof = { code: string } | { backupCode: string }\n\nexport interface TotpEnrollment {\n secret: string\n otpauthUrl: string\n}\n\nexport interface MfaSetupResult {\n token: string\n backupCodes: string[]\n}\n\nexport interface AuthPort {\n authConfig(): Observable<AuthConfig>\n\n login(username: string, password: string): Observable<LoginResponse>\n\n register(username: string, email: string, password: string): Observable<LoginResponse>\n\n /** `username` is passed only when the page lets the invitee choose it (`chooseUsername`). */\n activate(token: string, password: string, username?: string): Observable<void>\n\n resetPassword(token: string, password: string): Observable<void>\n\n verifyMfa(mfaToken: string, proof: MfaProof): Observable<void>\n\n startPasskeyChallenge(mfaToken: string): Observable<PasskeyChallenge>\n\n finishPasskeyChallenge(\n mfaToken: string,\n challengeId: string,\n credential: unknown,\n ): Observable<void>\n\n enrollTotp(mfaToken: string): Observable<TotpEnrollment>\n\n confirmTotp(mfaToken: string, code: string): Observable<MfaSetupResult>\n\n startPasskeySetup(mfaToken: string): Observable<PasskeyChallenge>\n\n finishPasskeySetup(\n mfaToken: string,\n challengeId: string,\n credential: unknown,\n name: string,\n ): Observable<MfaSetupResult>\n\n setToken(token: string): void\n}\n\nexport const AUTH_PORT = new InjectionToken<AuthPort>('AUTH_PORT')\n","import { InjectionToken } from '@angular/core'\nimport type { Observable } from 'rxjs'\nimport type { PasskeyChallenge, TotpEnrollment } from './auth.port'\n\nexport interface Passkey {\n id: string\n name: string\n createdAt: string\n lastUsedAt: string | null\n}\n\nexport interface MfaStatus {\n totpEnabled: boolean\n backupCodesRemaining: number\n passkeys: Passkey[]\n}\n\nexport interface BackupCodesResult {\n backupCodes: string[]\n}\n\nexport interface MfaPort {\n status(): Observable<MfaStatus>\n\n enroll(currentPassword: string): Observable<TotpEnrollment>\n\n confirm(code: string): Observable<BackupCodesResult>\n\n regenerate(currentPassword: string): Observable<BackupCodesResult>\n\n disable(currentPassword: string): Observable<void>\n\n startPasskeyRegistration(currentPassword: string): Observable<PasskeyChallenge>\n\n finishPasskeyRegistration(\n challengeId: string,\n credential: unknown,\n name: string,\n ): Observable<Passkey>\n\n deletePasskey(id: string, currentPassword: string): Observable<void>\n}\n\nexport const MFA_PORT = new InjectionToken<MfaPort>('MFA_PORT')\n","export interface AuthPortError {\n status: number\n error?: unknown\n}\n\nexport const AUTH_PORT_ERROR_BODIES = {\n invalidToken: 'invalid or expired token',\n invalidCode: 'invalid code',\n alreadySetUp: 'MFA is already set up',\n wrongPassword: 'current password is incorrect',\n tooManyPasskeys: 'too many passkeys',\n registrationDisabled: 'registration is disabled',\n usernameReserved: 'username is reserved',\n emailTaken: 'email already in use',\n invalidEmail: 'email is not a valid address',\n weakPasswordPrefix: 'password must be at least',\n usernamePrefix: 'username ',\n} as const\n\nexport function isAuthPortError(err: unknown): err is AuthPortError {\n return (\n typeof err === 'object' &&\n err !== null &&\n typeof (err as { status?: unknown }).status === 'number'\n )\n}\n\nexport function portErrorMessage(err: AuthPortError): string | null {\n const body = err.error\n if (\n typeof body === 'object' &&\n body !== null &&\n 'error' in body &&\n typeof (body as { error: unknown }).error === 'string'\n ) {\n return (body as { error: string }).error\n }\n return null\n}\n","import { AUTH_PORT_ERROR_BODIES, isAuthPortError, portErrorMessage } from './port-error'\n\nexport type RegisterFailure =\n | 'disabled'\n | 'invalid'\n | 'username-invalid'\n | 'email-invalid'\n | 'password-weak'\n | 'username-reserved'\n | 'username-taken'\n | 'email-taken'\n | 'rate-limited'\n | 'other'\n\nexport type ActivateFailure =\n | 'invalid-link'\n | 'weak-password'\n | 'username-invalid'\n | 'username-reserved'\n | 'username-taken'\n | 'rate-limited'\n | 'other'\n\nexport function classifyRegisterFailure(err: unknown): RegisterFailure {\n if (!isAuthPortError(err)) {\n return 'other'\n }\n const message = portErrorMessage(err)\n switch (err.status) {\n case 400:\n if (message === AUTH_PORT_ERROR_BODIES.registrationDisabled) {\n return 'disabled'\n }\n if (message === AUTH_PORT_ERROR_BODIES.usernameReserved) {\n return 'username-reserved'\n }\n if (message === AUTH_PORT_ERROR_BODIES.invalidEmail) {\n return 'email-invalid'\n }\n if (message?.startsWith(AUTH_PORT_ERROR_BODIES.weakPasswordPrefix)) {\n return 'password-weak'\n }\n return message?.startsWith(AUTH_PORT_ERROR_BODIES.usernamePrefix)\n ? 'username-invalid'\n : 'invalid'\n case 409:\n return message === AUTH_PORT_ERROR_BODIES.emailTaken ? 'email-taken' : 'username-taken'\n case 429:\n return 'rate-limited'\n default:\n return 'other'\n }\n}\n\nexport function classifyActivateFailure(err: unknown): ActivateFailure {\n if (!isAuthPortError(err)) {\n return 'other'\n }\n const message = portErrorMessage(err)\n switch (err.status) {\n case 400:\n if (message?.startsWith(AUTH_PORT_ERROR_BODIES.weakPasswordPrefix)) {\n return 'weak-password'\n }\n if (message === AUTH_PORT_ERROR_BODIES.usernameReserved) {\n return 'username-reserved'\n }\n return message?.startsWith(AUTH_PORT_ERROR_BODIES.usernamePrefix)\n ? 'username-invalid'\n : 'invalid-link'\n case 409:\n return 'username-taken'\n case 429:\n return 'rate-limited'\n default:\n return 'other'\n }\n}\n","export const MIN_PASSWORD_LENGTH = 8\n\nexport const USERNAME_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{2,31}$/\n\nconst MAX_EMAIL_LENGTH = 254\n\nexport type UsernameProblem = 'empty' | 'invalid'\nexport type EmailProblem = 'empty' | 'invalid'\nexport type PasswordProblem = 'empty' | 'too-short'\n\nexport function usernameProblem(\n raw: string,\n pattern: RegExp = USERNAME_PATTERN,\n): UsernameProblem | null {\n const username = raw.trim()\n if (username === '') {\n return 'empty'\n }\n return pattern.test(username) ? null : 'invalid'\n}\n\nexport function emailProblem(raw: string): EmailProblem | null {\n const email = raw.trim()\n if (email === '') {\n return 'empty'\n }\n const parts = email.split('@')\n const [local, domain] = parts\n const valid =\n email.length <= MAX_EMAIL_LENGTH &&\n !/\\s/.test(email) &&\n parts.length === 2 &&\n local.length > 0 &&\n domain.includes('.') &&\n !domain.startsWith('.') &&\n !domain.endsWith('.')\n return valid ? null : 'invalid'\n}\n\nexport function passwordProblem(\n password: string,\n minLength: number = MIN_PASSWORD_LENGTH,\n): PasswordProblem | null {\n if (password === '') {\n return 'empty'\n }\n return password.length >= minLength ? null : 'too-short'\n}\n\nexport function accountName(raw: string): string {\n return raw.trim().toLowerCase()\n}\n","export const ACTIVATION_TOKEN_SHAPE = /^[0-9a-f]{64}$/i\n\nexport function activationToken(\n fragment: string | null,\n query: string | null,\n shape: RegExp = ACTIVATION_TOKEN_SHAPE,\n): string | null {\n const fromFragment = new URLSearchParams((fragment ?? '').replace(/^#/, '')).get('token')\n const raw = fromFragment ?? query\n return raw !== null && shape.test(raw) ? raw : null\n}\n","import { ElementRef, Injector, afterNextRender } from '@angular/core'\n\nexport interface FocusOptions {\n nestedFallback?: string\n}\n\nexport function focusNow(\n host: ElementRef<HTMLElement>,\n selector: string,\n options?: FocusOptions,\n): void {\n const target = host.nativeElement.querySelector<HTMLElement>(selector)\n const element =\n options?.nestedFallback && !target?.matches('input, button')\n ? target?.querySelector<HTMLElement>(options.nestedFallback)\n : target\n element?.focus()\n}\n\n/** `selector` may be a thunk to defer evaluation until after render (e.g. a signal input not yet settled at construction time). */\nexport function focusAfterRender(\n host: ElementRef<HTMLElement>,\n injector: Injector,\n selector: string | (() => string),\n options?: FocusOptions,\n): void {\n afterNextRender(\n () => focusNow(host, typeof selector === 'function' ? selector() : selector, options),\n {\n injector,\n },\n )\n}\n","import { AUTH_PORT_ERROR_BODIES, isAuthPortError, portErrorMessage } from './port-error'\n\nexport type MfaFailure =\n 'wrong-code' | 'expired' | 'rate-limited' | 'unavailable' | 'already-set-up' | 'other'\n\nexport function classifyMfaFailure(err: unknown): MfaFailure {\n if (!isAuthPortError(err)) {\n return 'other'\n }\n const message = portErrorMessage(err)\n switch (err.status) {\n case 429:\n return 'rate-limited'\n case 503:\n return 'unavailable'\n case 401:\n return message === AUTH_PORT_ERROR_BODIES.invalidToken ? 'expired' : 'wrong-code'\n case 400:\n if (message === AUTH_PORT_ERROR_BODIES.invalidCode) {\n return 'wrong-code'\n }\n return message === AUTH_PORT_ERROR_BODIES.alreadySetUp ? 'already-set-up' : 'other'\n default:\n return 'other'\n }\n}\n\nexport type PasswordGatedFailure = 'wrong-password' | 'rate-limited' | 'other'\n\nexport function classifyPasswordFailure(err: unknown): PasswordGatedFailure {\n if (!isAuthPortError(err)) {\n return 'other'\n }\n if (err.status === 429) {\n return 'rate-limited'\n }\n if (err.status === 400) {\n return portErrorMessage(err) === AUTH_PORT_ERROR_BODIES.wrongPassword\n ? 'wrong-password'\n : 'other'\n }\n return 'other'\n}\n\nexport function isTooManyPasskeys(err: unknown): boolean {\n return (\n isAuthPortError(err) &&\n err.status === 400 &&\n portErrorMessage(err) === AUTH_PORT_ERROR_BODIES.tooManyPasskeys\n )\n}\n","import { Injectable, signal } from '@angular/core'\nimport type { MfaStatus } from '../ports/mfa.port'\n\nexport type MfaFormOwner = 'passkeys' | 'app'\n\n@Injectable({ providedIn: 'root' })\nexport class MfaSettingsState {\n private readonly passkeys = signal<number | null>(null)\n private readonly totp = signal<boolean | null>(null)\n private readonly owner = signal<MfaFormOwner | null>(null)\n private readonly appFlow = signal(false)\n\n readonly passkeyCount = this.passkeys.asReadonly()\n\n readonly totpEnabled = this.totp.asReadonly()\n\n readonly formOwner = this.owner.asReadonly()\n\n readonly appFlowActive = this.appFlow.asReadonly()\n\n claimForm(owner: MfaFormOwner): void {\n this.owner.set(owner)\n }\n\n setAppFlowActive(active: boolean): void {\n this.appFlow.set(active)\n }\n\n statusLoaded(status: MfaStatus): void {\n this.passkeys.set(status.passkeys.length)\n this.totp.set(status.totpEnabled)\n }\n\n totpConfirmed(): void {\n this.totp.set(true)\n }\n\n passkeyAdded(): void {\n this.passkeys.update((count) => (count === null ? count : count + 1))\n }\n\n passkeyGone(): void {\n this.passkeys.update((count) => (count === null ? count : Math.max(0, count - 1)))\n }\n}\n","export const PASSKEY_NAME_MAX = 40\n\nexport type PasskeyNameProblem = 'too-long' | 'control-characters'\n\nexport function passkeyNameProblem(\n name: string,\n maxLength: number = PASSKEY_NAME_MAX,\n): PasskeyNameProblem | null {\n if (Array.from(name).length > maxLength) {\n return 'too-long'\n }\n // eslint-disable-next-line no-control-regex\n return /[\\u0000-\\u001f\\u007f-\\u009f]/.test(name) ? 'control-characters' : null\n}\n","export type PasskeyFailure = 'cancelled' | 'already-registered' | 'unsupported' | 'failed'\n\nexport function bufferToBase64Url(buffer: ArrayBuffer): string {\n let binary = ''\n for (const byte of new Uint8Array(buffer)) {\n binary += String.fromCharCode(byte)\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nexport function base64UrlToBuffer(base64Url: string): ArrayBuffer {\n const unpadded = base64Url.replace(/=+$/, '')\n const base64 = (unpadded + '='.repeat((4 - (unpadded.length % 4)) % 4))\n .replace(/-/g, '+')\n .replace(/_/g, '/')\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes.buffer\n}\n\nexport function passkeysSupported(): boolean {\n return (\n typeof PublicKeyCredential !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n !!navigator.credentials &&\n typeof navigator.credentials.create === 'function' &&\n typeof navigator.credentials.get === 'function'\n )\n}\n\nexport function classifyPasskeyError(e: unknown): PasskeyFailure {\n const name =\n typeof e === 'object' && e !== null && 'name' in e ? (e as { name: unknown }).name : null\n switch (name) {\n case 'NotAllowedError':\n case 'AbortError':\n return 'cancelled'\n case 'InvalidStateError':\n return 'already-registered'\n case 'NotSupportedError':\n return 'unsupported'\n default:\n return 'failed'\n }\n}\n\ninterface CredentialDescriptorJson {\n id: string\n [key: string]: unknown\n}\n\nfunction ceremonyError(\n message: string,\n name: 'NotSupportedError' | 'NotAllowedError' | 'DataError',\n): DOMException {\n return new DOMException(message, name)\n}\n\nfunction decodeDescriptors(list: unknown): PublicKeyCredentialDescriptor[] {\n if (list === undefined || list === null) {\n return []\n }\n return (list as CredentialDescriptorJson[]).map(\n (descriptor) =>\n ({ ...descriptor, id: base64UrlToBuffer(descriptor.id) }) as PublicKeyCredentialDescriptor,\n )\n}\n\nfunction asOptions(options: unknown): Record<string, unknown> {\n if (typeof options !== 'object' || options === null) {\n throw ceremonyError('The passkey options are not an object', 'DataError')\n }\n return options as Record<string, unknown>\n}\n\nexport async function createPasskeyCredential(publicKey: unknown): Promise<unknown> {\n if (!passkeysSupported()) {\n throw ceremonyError('WebAuthn is not available in this browser', 'NotSupportedError')\n }\n const options = asOptions(publicKey)\n const user = options['user'] as { id: string } | null | undefined\n if (typeof options['challenge'] !== 'string' || typeof user?.id !== 'string') {\n throw ceremonyError('The passkey options are incomplete', 'DataError')\n }\n const decoded = {\n ...options,\n challenge: base64UrlToBuffer(options['challenge']),\n user: { ...user, id: base64UrlToBuffer(user.id) },\n excludeCredentials: decodeDescriptors(options['excludeCredentials']),\n } as unknown as PublicKeyCredentialCreationOptions\n\n const credential = (await navigator.credentials.create({\n publicKey: decoded,\n })) as PublicKeyCredential | null\n if (!credential) {\n throw ceremonyError('No credential was created', 'NotAllowedError')\n }\n const response = credential.response as AuthenticatorAttestationResponse\n return {\n id: credential.id,\n rawId: bufferToBase64Url(credential.rawId),\n type: credential.type,\n response: {\n attestationObject: bufferToBase64Url(response.attestationObject),\n clientDataJSON: bufferToBase64Url(response.clientDataJSON),\n },\n }\n}\n\nexport async function getPasskeyAssertion(publicKey: unknown): Promise<unknown> {\n if (!passkeysSupported()) {\n throw ceremonyError('WebAuthn is not available in this browser', 'NotSupportedError')\n }\n const options = asOptions(publicKey)\n if (typeof options['challenge'] !== 'string') {\n throw ceremonyError('The passkey options are incomplete', 'DataError')\n }\n const decoded = {\n ...options,\n challenge: base64UrlToBuffer(options['challenge']),\n allowCredentials: decodeDescriptors(options['allowCredentials']),\n } as unknown as PublicKeyCredentialRequestOptions\n\n const credential = (await navigator.credentials.get({\n publicKey: decoded,\n })) as PublicKeyCredential | null\n if (!credential) {\n throw ceremonyError('No credential was returned', 'NotAllowedError')\n }\n const response = credential.response as AuthenticatorAssertionResponse\n return {\n id: credential.id,\n rawId: bufferToBase64Url(credential.rawId),\n type: credential.type,\n response: {\n authenticatorData: bufferToBase64Url(response.authenticatorData),\n clientDataJSON: bufferToBase64Url(response.clientDataJSON),\n signature: bufferToBase64Url(response.signature),\n userHandle: response.userHandle ? bufferToBase64Url(response.userHandle) : null,\n },\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, ElementRef, booleanAttribute, computed, forwardRef, inject, input, output, signal } from "@angular/core";
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from "@angular/forms";
|
|
4
|
+
import { NgTemplateOutlet } from "@angular/common";
|
|
5
|
+
import { isObservable } from "rxjs";
|
|
6
|
+
import { floatingPanelAnchor, followPageScroll } from "@masmarino/gabarit/floating-panel";
|
|
7
|
+
let nextAutocompleteId = 0;
|
|
8
|
+
var Autocomplete = class Autocomplete {
|
|
9
|
+
elementRef = inject(ElementRef);
|
|
10
|
+
id = input(`gbt-autocomplete-${++nextAutocompleteId}`, ...ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []);
|
|
11
|
+
label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
12
|
+
placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
|
|
13
|
+
disabled = input(false, {
|
|
14
|
+
...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
|
|
15
|
+
transform: booleanAttribute
|
|
16
|
+
});
|
|
17
|
+
required = input(false, {
|
|
18
|
+
...ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {},
|
|
19
|
+
transform: booleanAttribute
|
|
20
|
+
});
|
|
21
|
+
errorMessage = input(null, ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
|
|
22
|
+
search = input.required(...ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []);
|
|
23
|
+
displayFn = input((item) => String(item), ...ngDevMode ? [{ debugName: "displayFn" }] : /* istanbul ignore next */ []);
|
|
24
|
+
itemTemplate = input(...ngDevMode ? [void 0, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []);
|
|
25
|
+
debounceMs = input(300, ...ngDevMode ? [{ debugName: "debounceMs" }] : /* istanbul ignore next */ []);
|
|
26
|
+
minLength = input(1, ...ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []);
|
|
27
|
+
loadingMessage = input("Searching…", ...ngDevMode ? [{ debugName: "loadingMessage" }] : /* istanbul ignore next */ []);
|
|
28
|
+
noResultsMessage = input("No results", ...ngDevMode ? [{ debugName: "noResultsMessage" }] : /* istanbul ignore next */ []);
|
|
29
|
+
searchErrorMessage = input("Search failed", ...ngDevMode ? [{ debugName: "searchErrorMessage" }] : /* istanbul ignore next */ []);
|
|
30
|
+
resultsAnnouncement = input((count) => `${count} result${count !== 1 ? "s" : ""}`, ...ngDevMode ? [{ debugName: "resultsAnnouncement" }] : /* istanbul ignore next */ []);
|
|
31
|
+
itemSelected = output();
|
|
32
|
+
query = signal("", ...ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []);
|
|
33
|
+
open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
|
|
34
|
+
results = signal([], ...ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []);
|
|
35
|
+
loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
|
|
36
|
+
searchFailed = signal(false, ...ngDevMode ? [{ debugName: "searchFailed" }] : /* istanbul ignore next */ []);
|
|
37
|
+
activeIndex = signal(0, ...ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []);
|
|
38
|
+
selectedItem = signal(null, ...ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []);
|
|
39
|
+
panelStyle = signal(null, ...ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []);
|
|
40
|
+
formDisabled = signal(false, ...ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []);
|
|
41
|
+
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []);
|
|
42
|
+
hasNoResults = computed(() => this.open() && !this.loading() && !this.searchFailed() && this.results().length === 0, ...ngDevMode ? [{ debugName: "hasNoResults" }] : /* istanbul ignore next */ []);
|
|
43
|
+
activeOptionId = computed(() => this.open() && this.results().length > 0 ? `${this.id()}-option-${this.activeIndex()}` : null, ...ngDevMode ? [{ debugName: "activeOptionId" }] : /* istanbul ignore next */ []);
|
|
44
|
+
onChange = () => {};
|
|
45
|
+
onTouched = () => {};
|
|
46
|
+
requestSeq = 0;
|
|
47
|
+
debounceHandle;
|
|
48
|
+
subscription;
|
|
49
|
+
setDisabledState(isDisabled) {
|
|
50
|
+
this.formDisabled.set(isDisabled);
|
|
51
|
+
}
|
|
52
|
+
writeValue(value) {
|
|
53
|
+
this.selectedItem.set(value);
|
|
54
|
+
this.query.set(value === null || value === void 0 ? "" : this.displayFn()(value));
|
|
55
|
+
}
|
|
56
|
+
registerOnChange(fn) {
|
|
57
|
+
this.onChange = fn;
|
|
58
|
+
}
|
|
59
|
+
registerOnTouched(fn) {
|
|
60
|
+
this.onTouched = fn;
|
|
61
|
+
}
|
|
62
|
+
onInput(event) {
|
|
63
|
+
const value = event.target.value;
|
|
64
|
+
this.query.set(value);
|
|
65
|
+
this.activeIndex.set(0);
|
|
66
|
+
if (this.selectedItem() !== null) {
|
|
67
|
+
this.selectedItem.set(null);
|
|
68
|
+
this.onChange(null);
|
|
69
|
+
}
|
|
70
|
+
this.scheduleSearch(value);
|
|
71
|
+
}
|
|
72
|
+
onFocus() {
|
|
73
|
+
if (this.query().trim().length >= this.minLength() && (this.results().length > 0 || this.searchFailed())) {
|
|
74
|
+
this.open.set(true);
|
|
75
|
+
this.updatePanelPosition();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
onBlur() {
|
|
79
|
+
this.onTouched();
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
if (!this.elementRef.nativeElement.contains(document.activeElement)) this.open.set(false);
|
|
82
|
+
}, 200);
|
|
83
|
+
}
|
|
84
|
+
scheduleSearch(value) {
|
|
85
|
+
clearTimeout(this.debounceHandle);
|
|
86
|
+
if (value.trim().length < this.minLength()) {
|
|
87
|
+
this.requestSeq++;
|
|
88
|
+
this.subscription?.unsubscribe();
|
|
89
|
+
this.open.set(false);
|
|
90
|
+
this.results.set([]);
|
|
91
|
+
this.loading.set(false);
|
|
92
|
+
this.searchFailed.set(false);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.debounceHandle = setTimeout(() => this.runSearch(value), this.debounceMs());
|
|
96
|
+
}
|
|
97
|
+
runSearch(query) {
|
|
98
|
+
const seq = ++this.requestSeq;
|
|
99
|
+
this.subscription?.unsubscribe();
|
|
100
|
+
this.loading.set(true);
|
|
101
|
+
this.searchFailed.set(false);
|
|
102
|
+
this.open.set(true);
|
|
103
|
+
this.updatePanelPosition();
|
|
104
|
+
const applyResults = (items) => {
|
|
105
|
+
if (seq !== this.requestSeq) return;
|
|
106
|
+
this.results.set(items);
|
|
107
|
+
this.loading.set(false);
|
|
108
|
+
this.activeIndex.set(0);
|
|
109
|
+
this.updatePanelPosition();
|
|
110
|
+
};
|
|
111
|
+
const applyError = () => {
|
|
112
|
+
if (seq !== this.requestSeq) return;
|
|
113
|
+
this.results.set([]);
|
|
114
|
+
this.loading.set(false);
|
|
115
|
+
this.searchFailed.set(true);
|
|
116
|
+
this.updatePanelPosition();
|
|
117
|
+
};
|
|
118
|
+
const result = this.search()(query);
|
|
119
|
+
if (isObservable(result)) this.subscription = result.subscribe({
|
|
120
|
+
next: applyResults,
|
|
121
|
+
error: applyError
|
|
122
|
+
});
|
|
123
|
+
else result.then(applyResults, applyError);
|
|
124
|
+
}
|
|
125
|
+
constructor() {
|
|
126
|
+
followPageScroll(() => this.updatePanelPosition());
|
|
127
|
+
}
|
|
128
|
+
updatePanelPosition() {
|
|
129
|
+
const trigger = this.elementRef.nativeElement.querySelector(".gbt-autocomplete__input");
|
|
130
|
+
const anchor = floatingPanelAnchor(this.open(), trigger);
|
|
131
|
+
if (anchor) this.panelStyle.set({
|
|
132
|
+
top: `${anchor.bottom}px`,
|
|
133
|
+
left: `${anchor.left}px`,
|
|
134
|
+
width: `${anchor.rect.width}px`
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
selectOption(item) {
|
|
138
|
+
this.selectedItem.set(item);
|
|
139
|
+
this.query.set(this.displayFn()(item));
|
|
140
|
+
this.results.set([]);
|
|
141
|
+
this.open.set(false);
|
|
142
|
+
this.onChange(item);
|
|
143
|
+
this.onTouched();
|
|
144
|
+
this.itemSelected.emit(item);
|
|
145
|
+
}
|
|
146
|
+
onKeydown(event) {
|
|
147
|
+
if (this.isDisabled()) return;
|
|
148
|
+
if (event.key === "Escape") {
|
|
149
|
+
if (this.open()) {
|
|
150
|
+
event.preventDefault();
|
|
151
|
+
event.stopPropagation();
|
|
152
|
+
this.open.set(false);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (!this.open() || this.results().length === 0) return;
|
|
157
|
+
const results = this.results();
|
|
158
|
+
switch (event.key) {
|
|
159
|
+
case "ArrowDown":
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
this.activeIndex.update((i) => Math.min(i + 1, results.length - 1));
|
|
162
|
+
break;
|
|
163
|
+
case "ArrowUp":
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
this.activeIndex.update((i) => Math.max(i - 1, 0));
|
|
166
|
+
break;
|
|
167
|
+
case "Enter": {
|
|
168
|
+
event.preventDefault();
|
|
169
|
+
const active = results[this.activeIndex()];
|
|
170
|
+
if (active) this.selectOption(active);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
ngOnDestroy() {
|
|
176
|
+
clearTimeout(this.debounceHandle);
|
|
177
|
+
this.subscription?.unsubscribe();
|
|
178
|
+
}
|
|
179
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
180
|
+
minVersion: "12.0.0",
|
|
181
|
+
version: "22.2.0",
|
|
182
|
+
ngImport: i0,
|
|
183
|
+
type: Autocomplete,
|
|
184
|
+
deps: [],
|
|
185
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
186
|
+
});
|
|
187
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
188
|
+
minVersion: "17.0.0",
|
|
189
|
+
version: "22.2.0",
|
|
190
|
+
type: Autocomplete,
|
|
191
|
+
isStandalone: true,
|
|
192
|
+
selector: "gbt-autocomplete",
|
|
193
|
+
inputs: {
|
|
194
|
+
id: {
|
|
195
|
+
classPropertyName: "id",
|
|
196
|
+
publicName: "id",
|
|
197
|
+
isSignal: true,
|
|
198
|
+
isRequired: false,
|
|
199
|
+
transformFunction: null
|
|
200
|
+
},
|
|
201
|
+
label: {
|
|
202
|
+
classPropertyName: "label",
|
|
203
|
+
publicName: "label",
|
|
204
|
+
isSignal: true,
|
|
205
|
+
isRequired: false,
|
|
206
|
+
transformFunction: null
|
|
207
|
+
},
|
|
208
|
+
placeholder: {
|
|
209
|
+
classPropertyName: "placeholder",
|
|
210
|
+
publicName: "placeholder",
|
|
211
|
+
isSignal: true,
|
|
212
|
+
isRequired: false,
|
|
213
|
+
transformFunction: null
|
|
214
|
+
},
|
|
215
|
+
disabled: {
|
|
216
|
+
classPropertyName: "disabled",
|
|
217
|
+
publicName: "disabled",
|
|
218
|
+
isSignal: true,
|
|
219
|
+
isRequired: false,
|
|
220
|
+
transformFunction: null
|
|
221
|
+
},
|
|
222
|
+
required: {
|
|
223
|
+
classPropertyName: "required",
|
|
224
|
+
publicName: "required",
|
|
225
|
+
isSignal: true,
|
|
226
|
+
isRequired: false,
|
|
227
|
+
transformFunction: null
|
|
228
|
+
},
|
|
229
|
+
errorMessage: {
|
|
230
|
+
classPropertyName: "errorMessage",
|
|
231
|
+
publicName: "errorMessage",
|
|
232
|
+
isSignal: true,
|
|
233
|
+
isRequired: false,
|
|
234
|
+
transformFunction: null
|
|
235
|
+
},
|
|
236
|
+
search: {
|
|
237
|
+
classPropertyName: "search",
|
|
238
|
+
publicName: "search",
|
|
239
|
+
isSignal: true,
|
|
240
|
+
isRequired: true,
|
|
241
|
+
transformFunction: null
|
|
242
|
+
},
|
|
243
|
+
displayFn: {
|
|
244
|
+
classPropertyName: "displayFn",
|
|
245
|
+
publicName: "displayFn",
|
|
246
|
+
isSignal: true,
|
|
247
|
+
isRequired: false,
|
|
248
|
+
transformFunction: null
|
|
249
|
+
},
|
|
250
|
+
itemTemplate: {
|
|
251
|
+
classPropertyName: "itemTemplate",
|
|
252
|
+
publicName: "itemTemplate",
|
|
253
|
+
isSignal: true,
|
|
254
|
+
isRequired: false,
|
|
255
|
+
transformFunction: null
|
|
256
|
+
},
|
|
257
|
+
debounceMs: {
|
|
258
|
+
classPropertyName: "debounceMs",
|
|
259
|
+
publicName: "debounceMs",
|
|
260
|
+
isSignal: true,
|
|
261
|
+
isRequired: false,
|
|
262
|
+
transformFunction: null
|
|
263
|
+
},
|
|
264
|
+
minLength: {
|
|
265
|
+
classPropertyName: "minLength",
|
|
266
|
+
publicName: "minLength",
|
|
267
|
+
isSignal: true,
|
|
268
|
+
isRequired: false,
|
|
269
|
+
transformFunction: null
|
|
270
|
+
},
|
|
271
|
+
loadingMessage: {
|
|
272
|
+
classPropertyName: "loadingMessage",
|
|
273
|
+
publicName: "loadingMessage",
|
|
274
|
+
isSignal: true,
|
|
275
|
+
isRequired: false,
|
|
276
|
+
transformFunction: null
|
|
277
|
+
},
|
|
278
|
+
noResultsMessage: {
|
|
279
|
+
classPropertyName: "noResultsMessage",
|
|
280
|
+
publicName: "noResultsMessage",
|
|
281
|
+
isSignal: true,
|
|
282
|
+
isRequired: false,
|
|
283
|
+
transformFunction: null
|
|
284
|
+
},
|
|
285
|
+
searchErrorMessage: {
|
|
286
|
+
classPropertyName: "searchErrorMessage",
|
|
287
|
+
publicName: "searchErrorMessage",
|
|
288
|
+
isSignal: true,
|
|
289
|
+
isRequired: false,
|
|
290
|
+
transformFunction: null
|
|
291
|
+
},
|
|
292
|
+
resultsAnnouncement: {
|
|
293
|
+
classPropertyName: "resultsAnnouncement",
|
|
294
|
+
publicName: "resultsAnnouncement",
|
|
295
|
+
isSignal: true,
|
|
296
|
+
isRequired: false,
|
|
297
|
+
transformFunction: null
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
outputs: { itemSelected: "itemSelected" },
|
|
301
|
+
host: { listeners: { "window:resize": "updatePanelPosition()" } },
|
|
302
|
+
providers: [{
|
|
303
|
+
provide: NG_VALUE_ACCESSOR,
|
|
304
|
+
useExisting: forwardRef(() => Autocomplete),
|
|
305
|
+
multi: true
|
|
306
|
+
}],
|
|
307
|
+
ngImport: i0,
|
|
308
|
+
template: "<div class=\"gbt-autocomplete\" [class.gbt-autocomplete--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-autocomplete__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <input\n [id]=\"id()\"\n type=\"text\"\n class=\"gbt-autocomplete__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? id() + '-listbox' : null\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"query()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (open()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n @if (loading()) {\n {{ loadingMessage() }}\n } @else if (searchFailed()) {\n {{ searchErrorMessage() }}\n } @else {\n {{ resultsAnnouncement()(results().length) }}\n }\n </div>\n }\n\n @if (open() && panelStyle(); as style) {\n <div\n class=\"gbt-autocomplete__panel\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @if (loading()) {\n <div class=\"gbt-autocomplete__state\" role=\"status\">\n <span>{{ loadingMessage() }}</span>\n </div>\n } @else if (searchFailed()) {\n <div class=\"gbt-autocomplete__state gbt-autocomplete__state--error\" role=\"alert\">\n <span>{{ searchErrorMessage() }}</span>\n </div>\n } @else if (hasNoResults()) {\n <div class=\"gbt-autocomplete__state\" role=\"status\">\n <span>{{ noResultsMessage() }}</span>\n </div>\n } @else {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-autocomplete__list\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n >\n @for (item of results(); track $index; let i = $index) {\n <li role=\"presentation\">\n <button\n [id]=\"id() + '-option-' + i\"\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n class=\"gbt-autocomplete__option\"\n [class.gbt-autocomplete__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"i === activeIndex()\"\n (click)=\"selectOption(item)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (itemTemplate(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else {\n <span class=\"gbt-autocomplete__option-label\">{{ displayFn()(item) }}</span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </div>\n }\n\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-autocomplete__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n",
|
|
309
|
+
styles: [":host{display:block}.gbt-autocomplete{position:relative;display:flex;flex-direction:column;gap:.375rem}.gbt-autocomplete--disabled{opacity:.5}.gbt-autocomplete__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-autocomplete__input{box-sizing:border-box;width:100%;height:var(--gbt-control-height-md);padding:0 .75rem;font-family:var(--font-family);font-size:.875rem;color:var(--text-primary);background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);transition:border-color var(--site-transition-fast)}.gbt-autocomplete__input:focus{outline:none;border-color:var(--primary)}.gbt-autocomplete__input:focus-visible{outline:2px solid var(--gbt-focus-ring, var(--focus-ring));outline-offset:1px}.gbt-autocomplete__input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-autocomplete__panel{box-sizing:border-box;position:fixed;z-index:1000;margin:0;padding:6px;max-height:280px;overflow-y:auto;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-lg);animation:gbt-autocomplete-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-autocomplete__panel::-webkit-scrollbar{width:6px}.gbt-autocomplete__panel::-webkit-scrollbar-track{background:transparent}.gbt-autocomplete__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-autocomplete__list{margin:0;padding:0;list-style:none}.gbt-autocomplete__option{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:var(--gbt-radius-menu, 4px);color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-autocomplete__option:hover,.gbt-autocomplete__option--active{background:var(--bg-hover)}.gbt-autocomplete__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-autocomplete__state{padding:.75rem;font-size:.8125rem;color:var(--text-secondary);text-align:center}.gbt-autocomplete__state--error{color:var(--color-error-text)}@keyframes gbt-autocomplete-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-autocomplete__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-autocomplete__panel{animation:none}}\n"],
|
|
310
|
+
dependencies: [{
|
|
311
|
+
kind: "directive",
|
|
312
|
+
type: NgTemplateOutlet,
|
|
313
|
+
selector: "[ngTemplateOutlet]",
|
|
314
|
+
inputs: [
|
|
315
|
+
"ngTemplateOutletContext",
|
|
316
|
+
"ngTemplateOutlet",
|
|
317
|
+
"ngTemplateOutletInjector"
|
|
318
|
+
]
|
|
319
|
+
}],
|
|
320
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
324
|
+
minVersion: "12.0.0",
|
|
325
|
+
version: "22.2.0",
|
|
326
|
+
ngImport: i0,
|
|
327
|
+
type: Autocomplete,
|
|
328
|
+
decorators: [{
|
|
329
|
+
type: Component,
|
|
330
|
+
args: [{
|
|
331
|
+
selector: "gbt-autocomplete",
|
|
332
|
+
standalone: true,
|
|
333
|
+
imports: [NgTemplateOutlet],
|
|
334
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
335
|
+
host: { "(window:resize)": "updatePanelPosition()" },
|
|
336
|
+
providers: [{
|
|
337
|
+
provide: NG_VALUE_ACCESSOR,
|
|
338
|
+
useExisting: forwardRef(() => Autocomplete),
|
|
339
|
+
multi: true
|
|
340
|
+
}],
|
|
341
|
+
template: "<div class=\"gbt-autocomplete\" [class.gbt-autocomplete--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-autocomplete__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <input\n [id]=\"id()\"\n type=\"text\"\n class=\"gbt-autocomplete__input\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? id() + '-listbox' : null\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"query()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (open()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n @if (loading()) {\n {{ loadingMessage() }}\n } @else if (searchFailed()) {\n {{ searchErrorMessage() }}\n } @else {\n {{ resultsAnnouncement()(results().length) }}\n }\n </div>\n }\n\n @if (open() && panelStyle(); as style) {\n <div\n class=\"gbt-autocomplete__panel\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @if (loading()) {\n <div class=\"gbt-autocomplete__state\" role=\"status\">\n <span>{{ loadingMessage() }}</span>\n </div>\n } @else if (searchFailed()) {\n <div class=\"gbt-autocomplete__state gbt-autocomplete__state--error\" role=\"alert\">\n <span>{{ searchErrorMessage() }}</span>\n </div>\n } @else if (hasNoResults()) {\n <div class=\"gbt-autocomplete__state\" role=\"status\">\n <span>{{ noResultsMessage() }}</span>\n </div>\n } @else {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-autocomplete__list\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n >\n @for (item of results(); track $index; let i = $index) {\n <li role=\"presentation\">\n <button\n [id]=\"id() + '-option-' + i\"\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n class=\"gbt-autocomplete__option\"\n [class.gbt-autocomplete__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"i === activeIndex()\"\n (click)=\"selectOption(item)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (itemTemplate(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else {\n <span class=\"gbt-autocomplete__option-label\">{{ displayFn()(item) }}</span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </div>\n }\n\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-autocomplete__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n",
|
|
342
|
+
styles: [":host{display:block}.gbt-autocomplete{position:relative;display:flex;flex-direction:column;gap:.375rem}.gbt-autocomplete--disabled{opacity:.5}.gbt-autocomplete__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-autocomplete__input{box-sizing:border-box;width:100%;height:var(--gbt-control-height-md);padding:0 .75rem;font-family:var(--font-family);font-size:.875rem;color:var(--text-primary);background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);transition:border-color var(--site-transition-fast)}.gbt-autocomplete__input:focus{outline:none;border-color:var(--primary)}.gbt-autocomplete__input:focus-visible{outline:2px solid var(--gbt-focus-ring, var(--focus-ring));outline-offset:1px}.gbt-autocomplete__input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-autocomplete__panel{box-sizing:border-box;position:fixed;z-index:1000;margin:0;padding:6px;max-height:280px;overflow-y:auto;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-lg);animation:gbt-autocomplete-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-autocomplete__panel::-webkit-scrollbar{width:6px}.gbt-autocomplete__panel::-webkit-scrollbar-track{background:transparent}.gbt-autocomplete__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-autocomplete__list{margin:0;padding:0;list-style:none}.gbt-autocomplete__option{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:var(--gbt-radius-menu, 4px);color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-autocomplete__option:hover,.gbt-autocomplete__option--active{background:var(--bg-hover)}.gbt-autocomplete__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-autocomplete__state{padding:.75rem;font-size:.8125rem;color:var(--text-secondary);text-align:center}.gbt-autocomplete__state--error{color:var(--color-error-text)}@keyframes gbt-autocomplete-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-autocomplete__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-autocomplete__panel{animation:none}}\n"]
|
|
343
|
+
}]
|
|
344
|
+
}],
|
|
345
|
+
ctorParameters: () => [],
|
|
346
|
+
propDecorators: {
|
|
347
|
+
id: [{
|
|
348
|
+
type: i0.Input,
|
|
349
|
+
args: [{
|
|
350
|
+
isSignal: true,
|
|
351
|
+
alias: "id",
|
|
352
|
+
required: false
|
|
353
|
+
}]
|
|
354
|
+
}],
|
|
355
|
+
label: [{
|
|
356
|
+
type: i0.Input,
|
|
357
|
+
args: [{
|
|
358
|
+
isSignal: true,
|
|
359
|
+
alias: "label",
|
|
360
|
+
required: false
|
|
361
|
+
}]
|
|
362
|
+
}],
|
|
363
|
+
placeholder: [{
|
|
364
|
+
type: i0.Input,
|
|
365
|
+
args: [{
|
|
366
|
+
isSignal: true,
|
|
367
|
+
alias: "placeholder",
|
|
368
|
+
required: false
|
|
369
|
+
}]
|
|
370
|
+
}],
|
|
371
|
+
disabled: [{
|
|
372
|
+
type: i0.Input,
|
|
373
|
+
args: [{
|
|
374
|
+
isSignal: true,
|
|
375
|
+
alias: "disabled",
|
|
376
|
+
required: false
|
|
377
|
+
}]
|
|
378
|
+
}],
|
|
379
|
+
required: [{
|
|
380
|
+
type: i0.Input,
|
|
381
|
+
args: [{
|
|
382
|
+
isSignal: true,
|
|
383
|
+
alias: "required",
|
|
384
|
+
required: false
|
|
385
|
+
}]
|
|
386
|
+
}],
|
|
387
|
+
errorMessage: [{
|
|
388
|
+
type: i0.Input,
|
|
389
|
+
args: [{
|
|
390
|
+
isSignal: true,
|
|
391
|
+
alias: "errorMessage",
|
|
392
|
+
required: false
|
|
393
|
+
}]
|
|
394
|
+
}],
|
|
395
|
+
search: [{
|
|
396
|
+
type: i0.Input,
|
|
397
|
+
args: [{
|
|
398
|
+
isSignal: true,
|
|
399
|
+
alias: "search",
|
|
400
|
+
required: true
|
|
401
|
+
}]
|
|
402
|
+
}],
|
|
403
|
+
displayFn: [{
|
|
404
|
+
type: i0.Input,
|
|
405
|
+
args: [{
|
|
406
|
+
isSignal: true,
|
|
407
|
+
alias: "displayFn",
|
|
408
|
+
required: false
|
|
409
|
+
}]
|
|
410
|
+
}],
|
|
411
|
+
itemTemplate: [{
|
|
412
|
+
type: i0.Input,
|
|
413
|
+
args: [{
|
|
414
|
+
isSignal: true,
|
|
415
|
+
alias: "itemTemplate",
|
|
416
|
+
required: false
|
|
417
|
+
}]
|
|
418
|
+
}],
|
|
419
|
+
debounceMs: [{
|
|
420
|
+
type: i0.Input,
|
|
421
|
+
args: [{
|
|
422
|
+
isSignal: true,
|
|
423
|
+
alias: "debounceMs",
|
|
424
|
+
required: false
|
|
425
|
+
}]
|
|
426
|
+
}],
|
|
427
|
+
minLength: [{
|
|
428
|
+
type: i0.Input,
|
|
429
|
+
args: [{
|
|
430
|
+
isSignal: true,
|
|
431
|
+
alias: "minLength",
|
|
432
|
+
required: false
|
|
433
|
+
}]
|
|
434
|
+
}],
|
|
435
|
+
loadingMessage: [{
|
|
436
|
+
type: i0.Input,
|
|
437
|
+
args: [{
|
|
438
|
+
isSignal: true,
|
|
439
|
+
alias: "loadingMessage",
|
|
440
|
+
required: false
|
|
441
|
+
}]
|
|
442
|
+
}],
|
|
443
|
+
noResultsMessage: [{
|
|
444
|
+
type: i0.Input,
|
|
445
|
+
args: [{
|
|
446
|
+
isSignal: true,
|
|
447
|
+
alias: "noResultsMessage",
|
|
448
|
+
required: false
|
|
449
|
+
}]
|
|
450
|
+
}],
|
|
451
|
+
searchErrorMessage: [{
|
|
452
|
+
type: i0.Input,
|
|
453
|
+
args: [{
|
|
454
|
+
isSignal: true,
|
|
455
|
+
alias: "searchErrorMessage",
|
|
456
|
+
required: false
|
|
457
|
+
}]
|
|
458
|
+
}],
|
|
459
|
+
resultsAnnouncement: [{
|
|
460
|
+
type: i0.Input,
|
|
461
|
+
args: [{
|
|
462
|
+
isSignal: true,
|
|
463
|
+
alias: "resultsAnnouncement",
|
|
464
|
+
required: false
|
|
465
|
+
}]
|
|
466
|
+
}],
|
|
467
|
+
itemSelected: [{
|
|
468
|
+
type: i0.Output,
|
|
469
|
+
args: ["itemSelected"]
|
|
470
|
+
}]
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
export { Autocomplete };
|
|
474
|
+
|
|
475
|
+
//# sourceMappingURL=masmarino-gabarit-autocomplete.mjs.map
|