@masmarino/gabarit 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, input, computed, ChangeDetectionStrategy, Component, signal, viewChild, HostListener, booleanAttribute, output, forwardRef, ElementRef, effect, contentChildren, viewChildren, InjectionToken, isDevMode, Injector, afterNextRender } from '@angular/core';
2
+ import { Injectable, inject, input, computed, ChangeDetectionStrategy, Component, output, signal, viewChild, HostListener, booleanAttribute, forwardRef, ElementRef, effect, contentChildren, viewChildren, model, InjectionToken, isDevMode, Injector, afterNextRender } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import * as i1 from '@angular/forms';
6
+ import { NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule, FormsModule } from '@angular/forms';
4
7
  import { NgTemplateOutlet } from '@angular/common';
5
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
8
+ import { isObservable } from 'rxjs';
6
9
 
7
- const GABARIT_VERSION = '0.3.0';
10
+ const GABARIT_VERSION = '0.5.0';
8
11
 
9
12
  const BUILT_IN_ICONS = {
10
13
  search: `<path d="m21 21-4.34-4.34" />
@@ -18,6 +21,15 @@ const BUILT_IN_ICONS = {
18
21
  <path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" />
19
22
  <path d="m2 2 20 20" />`,
20
23
  'chevron-down': `<path d="m6 9 6 6 6-6" />`,
24
+ 'chevron-left': `<path d="m15 18-6-6 6-6" />`,
25
+ 'chevron-right': `<path d="m9 18 6-6-6-6" />`,
26
+ 'chevrons-left': `<path d="m11 17-5-5 5-5" />
27
+ <path d="m18 17-5-5 5-5" />`,
28
+ 'chevrons-right': `<path d="m6 17 5-5-5-5" />
29
+ <path d="m13 17 5-5-5-5" />`,
30
+ 'ellipsis-vertical': `<circle cx="12" cy="12" r="1" />
31
+ <circle cx="12" cy="5" r="1" />
32
+ <circle cx="12" cy="19" r="1" />`,
21
33
  check: `<path d="M20 6 9 17l-5-5" />`,
22
34
  'check-circle': `<path d="m5 12 5 5 9-10" />`,
23
35
  'alert-circle': `<path d="M12 7v6" />
@@ -27,6 +39,10 @@ const BUILT_IN_ICONS = {
27
39
  <path d="M12 17h.01" />`,
28
40
  info: `<path d="M12 17v-6" />
29
41
  <path d="M12 7h.01" />`,
42
+ 'arrow-up': `<path d="m5 12 7-7 7 7" />
43
+ <path d="M12 19V5" />`,
44
+ 'arrow-down': `<path d="M12 5v14" />
45
+ <path d="m19 12-7 7-7-7" />`,
30
46
  };
31
47
 
32
48
  class IconRegistry {
@@ -75,7 +91,7 @@ class Icon {
75
91
  [innerHTML]="content"
76
92
  ></svg>
77
93
  }
78
- `, isInline: true, styles: [":host{display:inline-flex;width:1.25em;height:1.25em}svg{width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
94
+ `, isInline: true, styles: [":host{display:inline-flex;flex-shrink:0;width:1.25em;height:1.25em}svg{width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
79
95
  }
80
96
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Icon, decorators: [{
81
97
  type: Component,
@@ -95,7 +111,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
95
111
  }
96
112
  `, host: {
97
113
  '[attr.aria-hidden]': '"true"',
98
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;width:1.25em;height:1.25em}svg{width:100%;height:100%}\n"] }]
114
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;flex-shrink:0;width:1.25em;height:1.25em}svg{width:100%;height:100%}\n"] }]
99
115
  }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } });
100
116
 
101
117
  let nextId$3 = 0;
@@ -108,6 +124,15 @@ class AppShell {
108
124
  ...(ngDevMode ? [{ debugName: "openMenuLabel" }] : /* istanbul ignore next */ []));
109
125
  closeMenuLabel = input.required(/* @ts-ignore */
110
126
  ...(ngDevMode ? [{ debugName: "closeMenuLabel" }] : /* istanbul ignore next */ []));
127
+ collapseLabel = input('', /* @ts-ignore */
128
+ ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
129
+ expandLabel = input('', /* @ts-ignore */
130
+ ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
131
+ collapsed = input(false, /* @ts-ignore */
132
+ ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
133
+ collapsible = input(true, /* @ts-ignore */
134
+ ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
135
+ collapsedChange = output();
111
136
  id = ++nextId$3;
112
137
  mainId = `gbt-app-shell-main-${this.id}`;
113
138
  navId = `gbt-app-shell-nav-${this.id}`;
@@ -133,6 +158,9 @@ class AppShell {
133
158
  this.menuOpen.set(false);
134
159
  this.toggleButton()?.nativeElement.focus();
135
160
  }
161
+ toggleCollapsed() {
162
+ this.collapsedChange.emit(!this.collapsed());
163
+ }
136
164
  onEscape() {
137
165
  this.close();
138
166
  }
@@ -157,12 +185,12 @@ class AppShell {
157
185
  }
158
186
  }
159
187
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AppShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
160
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AppShell, isStandalone: true, selector: "gbt-app-shell", inputs: { navLabel: { classPropertyName: "navLabel", publicName: "navLabel", isSignal: true, isRequired: true, transformFunction: null }, skipLabel: { classPropertyName: "skipLabel", publicName: "skipLabel", isSignal: true, isRequired: true, transformFunction: null }, openMenuLabel: { classPropertyName: "openMenuLabel", publicName: "openMenuLabel", isSignal: true, isRequired: true, transformFunction: null }, closeMenuLabel: { classPropertyName: "closeMenuLabel", publicName: "closeMenuLabel", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "toggleButton", first: true, predicate: ["toggle"], descendants: true, isSignal: true }, { propertyName: "nav", first: true, predicate: ["nav"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-app-shell\">\n <a class=\"gbt-app-shell__skip\" [href]=\"'#' + mainId\">{{ skipLabel() }}</a>\n\n <nav\n #nav\n [id]=\"navId\"\n class=\"gbt-app-shell__nav\"\n [class.gbt-app-shell__nav--open]=\"menuOpen()\"\n [attr.aria-label]=\"navLabel()\"\n tabindex=\"-1\"\n (keydown)=\"onNavKeydown($event)\"\n >\n <div class=\"gbt-app-shell__brand\">\n <ng-content select=\"[shell-brand]\" />\n </div>\n <ng-content select=\"[shell-nav]\" />\n </nav>\n\n @if (menuOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-app-shell__scrim\" (click)=\"close()\"></div>\n }\n\n <div class=\"gbt-app-shell__body\">\n <header class=\"gbt-app-shell__header\">\n <button\n #toggle\n type=\"button\"\n class=\"gbt-app-shell__toggle\"\n [attr.aria-expanded]=\"menuOpen()\"\n [attr.aria-controls]=\"navId\"\n [attr.aria-label]=\"menuLabel()\"\n (click)=\"toggleMenu()\"\n >\n <span class=\"gbt-app-shell__burger\" aria-hidden=\"true\"></span>\n </button>\n <ng-content select=\"[shell-header]\" />\n </header>\n\n <main [id]=\"mainId\" class=\"gbt-app-shell__content\" tabindex=\"-1\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-app-shell{display:flex;min-height:100vh;background:var(--bg-panel)}.gbt-app-shell__skip{position:absolute;left:-9999px;top:0;z-index:1040;padding:.5rem .75rem;border-radius:var(--site-border-radius-sm);background:var(--primary);color:var(--text-on-primary);font-size:.875rem;text-decoration:none}.gbt-app-shell__skip:focus-visible{left:.5rem;top:.5rem;outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__nav{display:flex;flex-direction:column;gap:.25rem;flex-shrink:0;box-sizing:border-box;width:220px;padding:1rem .75rem;background:var(--bg-panel);border-right:1px solid var(--border-color)}.gbt-app-shell__brand{margin-bottom:1rem}.gbt-app-shell__body{display:flex;flex-direction:column;flex:1;min-width:0}.gbt-app-shell__header{position:relative;z-index:1010;display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;border-bottom:1px solid var(--border-color)}.gbt-app-shell__toggle{display:none;flex-shrink:0;width:2.25rem;height:2.25rem;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:transparent;cursor:pointer}.gbt-app-shell__toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__burger{display:block;position:relative;width:1rem;height:2px;margin:0 auto;background:var(--text-primary)}.gbt-app-shell__burger:before,.gbt-app-shell__burger:after{content:\"\";position:absolute;left:0;width:100%;height:2px;background:var(--text-primary)}.gbt-app-shell__burger:before{top:-5px}.gbt-app-shell__burger:after{top:5px}.gbt-app-shell__content{flex:1;min-width:0;padding:1rem}.gbt-app-shell__content:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}@media(max-width:768px){.gbt-app-shell__toggle{display:block}.gbt-app-shell__nav{position:fixed;top:0;bottom:0;left:0;z-index:1030;transform:translate(-100%);transition:transform .16s ease-out}}@media(max-width:768px)and (prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}}@media(max-width:768px){.gbt-app-shell__nav--open{transform:translate(0)}.gbt-app-shell__scrim{position:fixed;inset:0;z-index:1020;background:#0006}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
188
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AppShell, isStandalone: true, selector: "gbt-app-shell", inputs: { navLabel: { classPropertyName: "navLabel", publicName: "navLabel", isSignal: true, isRequired: true, transformFunction: null }, skipLabel: { classPropertyName: "skipLabel", publicName: "skipLabel", isSignal: true, isRequired: true, transformFunction: null }, openMenuLabel: { classPropertyName: "openMenuLabel", publicName: "openMenuLabel", isSignal: true, isRequired: true, transformFunction: null }, closeMenuLabel: { classPropertyName: "closeMenuLabel", publicName: "closeMenuLabel", isSignal: true, isRequired: true, transformFunction: null }, collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedChange: "collapsedChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "toggleButton", first: true, predicate: ["toggle"], descendants: true, isSignal: true }, { propertyName: "nav", first: true, predicate: ["nav"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-app-shell\">\n <a class=\"gbt-app-shell__skip\" [href]=\"'#' + mainId\">{{ skipLabel() }}</a>\n\n <nav\n #nav\n [id]=\"navId\"\n class=\"gbt-app-shell__nav\"\n [class.gbt-app-shell__nav--open]=\"menuOpen()\"\n [class.gbt-app-shell__nav--collapsed]=\"collapsed()\"\n [attr.aria-label]=\"navLabel()\"\n tabindex=\"-1\"\n (keydown)=\"onNavKeydown($event)\"\n >\n <div class=\"gbt-app-shell__brand\">\n <ng-content select=\"[shell-brand]\" />\n </div>\n <ng-content select=\"[shell-nav]\" />\n @if (collapsible()) {\n <button\n type=\"button\"\n class=\"gbt-app-shell__collapse-toggle\"\n [class.gbt-app-shell__collapse-toggle--collapsed]=\"collapsed()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? expandLabel() : collapseLabel()\"\n (click)=\"toggleCollapsed()\"\n >\n <gbt-icon name=\"chevrons-left\" />\n </button>\n }\n </nav>\n\n @if (menuOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-app-shell__scrim\" (click)=\"close()\"></div>\n }\n\n <div class=\"gbt-app-shell__body\">\n <header class=\"gbt-app-shell__header\">\n <button\n #toggle\n type=\"button\"\n class=\"gbt-app-shell__toggle\"\n [attr.aria-expanded]=\"menuOpen()\"\n [attr.aria-controls]=\"navId\"\n [attr.aria-label]=\"menuLabel()\"\n (click)=\"toggleMenu()\"\n >\n <span class=\"gbt-app-shell__burger\" aria-hidden=\"true\"></span>\n </button>\n <ng-content select=\"[shell-header]\" />\n </header>\n\n <main [id]=\"mainId\" class=\"gbt-app-shell__content\" tabindex=\"-1\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-app-shell{display:flex;min-height:100vh;background:var(--bg-panel)}.gbt-app-shell__skip{position:absolute;left:-9999px;top:0;z-index:1040;padding:.5rem .75rem;border-radius:var(--site-border-radius-sm);background:var(--primary);color:var(--text-on-primary);font-size:.875rem;text-decoration:none}.gbt-app-shell__skip:focus-visible{left:.5rem;top:.5rem;outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__nav{display:flex;flex-direction:column;gap:.25rem;flex-shrink:0;box-sizing:border-box;width:220px;padding:1rem .75rem;background:var(--bg-panel);border-right:1px solid var(--border-color);overflow:hidden;transition:width .2s ease}@media(min-width:769px){.gbt-app-shell__nav--collapsed{width:64px}}.gbt-app-shell__brand{display:flex;align-items:center;gap:.625rem;margin-bottom:1rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gbt-app-shell__collapse-toggle{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.625rem;width:100%;margin-top:auto;padding:.5rem .75rem;border:none;border-radius:var(--site-border-radius-sm);background:transparent;color:var(--text-secondary);cursor:pointer}.gbt-app-shell__collapse-toggle:hover{background:var(--bg-hover)}.gbt-app-shell__collapse-toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__collapse-toggle gbt-icon{transition:transform .2s ease}.gbt-app-shell__collapse-toggle--collapsed gbt-icon{transform:rotate(180deg)}.gbt-app-shell__body{display:flex;flex-direction:column;flex:1;min-width:0}.gbt-app-shell__header{position:relative;z-index:1010;display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;border-bottom:1px solid var(--border-color)}.gbt-app-shell__toggle{display:none;flex-shrink:0;width:2.25rem;height:2.25rem;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:transparent;cursor:pointer}.gbt-app-shell__toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__burger{display:block;position:relative;width:1rem;height:2px;margin:0 auto;background:var(--text-primary)}.gbt-app-shell__burger:before,.gbt-app-shell__burger:after{content:\"\";position:absolute;left:0;width:100%;height:2px;background:var(--text-primary)}.gbt-app-shell__burger:before{top:-5px}.gbt-app-shell__burger:after{top:5px}.gbt-app-shell__content{flex:1;min-width:0;padding:1rem}.gbt-app-shell__content:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}@media(max-width:768px){.gbt-app-shell__toggle{display:block}.gbt-app-shell__nav{position:fixed;top:0;bottom:0;left:0;z-index:1030;transform:translate(-100%);transition:transform .16s ease-out}}@media(max-width:768px)and (prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}}@media(max-width:768px){.gbt-app-shell__nav--open{transform:translate(0)}.gbt-app-shell__scrim{position:fixed;inset:0;z-index:1020;background:#0006}}@media(prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}.gbt-app-shell__collapse-toggle gbt-icon{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
161
189
  }
162
190
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AppShell, decorators: [{
163
191
  type: Component,
164
- args: [{ selector: 'gbt-app-shell', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-app-shell\">\n <a class=\"gbt-app-shell__skip\" [href]=\"'#' + mainId\">{{ skipLabel() }}</a>\n\n <nav\n #nav\n [id]=\"navId\"\n class=\"gbt-app-shell__nav\"\n [class.gbt-app-shell__nav--open]=\"menuOpen()\"\n [attr.aria-label]=\"navLabel()\"\n tabindex=\"-1\"\n (keydown)=\"onNavKeydown($event)\"\n >\n <div class=\"gbt-app-shell__brand\">\n <ng-content select=\"[shell-brand]\" />\n </div>\n <ng-content select=\"[shell-nav]\" />\n </nav>\n\n @if (menuOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-app-shell__scrim\" (click)=\"close()\"></div>\n }\n\n <div class=\"gbt-app-shell__body\">\n <header class=\"gbt-app-shell__header\">\n <button\n #toggle\n type=\"button\"\n class=\"gbt-app-shell__toggle\"\n [attr.aria-expanded]=\"menuOpen()\"\n [attr.aria-controls]=\"navId\"\n [attr.aria-label]=\"menuLabel()\"\n (click)=\"toggleMenu()\"\n >\n <span class=\"gbt-app-shell__burger\" aria-hidden=\"true\"></span>\n </button>\n <ng-content select=\"[shell-header]\" />\n </header>\n\n <main [id]=\"mainId\" class=\"gbt-app-shell__content\" tabindex=\"-1\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-app-shell{display:flex;min-height:100vh;background:var(--bg-panel)}.gbt-app-shell__skip{position:absolute;left:-9999px;top:0;z-index:1040;padding:.5rem .75rem;border-radius:var(--site-border-radius-sm);background:var(--primary);color:var(--text-on-primary);font-size:.875rem;text-decoration:none}.gbt-app-shell__skip:focus-visible{left:.5rem;top:.5rem;outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__nav{display:flex;flex-direction:column;gap:.25rem;flex-shrink:0;box-sizing:border-box;width:220px;padding:1rem .75rem;background:var(--bg-panel);border-right:1px solid var(--border-color)}.gbt-app-shell__brand{margin-bottom:1rem}.gbt-app-shell__body{display:flex;flex-direction:column;flex:1;min-width:0}.gbt-app-shell__header{position:relative;z-index:1010;display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;border-bottom:1px solid var(--border-color)}.gbt-app-shell__toggle{display:none;flex-shrink:0;width:2.25rem;height:2.25rem;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:transparent;cursor:pointer}.gbt-app-shell__toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__burger{display:block;position:relative;width:1rem;height:2px;margin:0 auto;background:var(--text-primary)}.gbt-app-shell__burger:before,.gbt-app-shell__burger:after{content:\"\";position:absolute;left:0;width:100%;height:2px;background:var(--text-primary)}.gbt-app-shell__burger:before{top:-5px}.gbt-app-shell__burger:after{top:5px}.gbt-app-shell__content{flex:1;min-width:0;padding:1rem}.gbt-app-shell__content:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}@media(max-width:768px){.gbt-app-shell__toggle{display:block}.gbt-app-shell__nav{position:fixed;top:0;bottom:0;left:0;z-index:1030;transform:translate(-100%);transition:transform .16s ease-out}}@media(max-width:768px)and (prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}}@media(max-width:768px){.gbt-app-shell__nav--open{transform:translate(0)}.gbt-app-shell__scrim{position:fixed;inset:0;z-index:1020;background:#0006}}\n"] }]
165
- }], propDecorators: { navLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "navLabel", required: true }] }], skipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLabel", required: true }] }], openMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "openMenuLabel", required: true }] }], closeMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeMenuLabel", required: true }] }], toggleButton: [{ type: i0.ViewChild, args: ['toggle', { isSignal: true }] }], nav: [{ type: i0.ViewChild, args: ['nav', { isSignal: true }] }], onEscape: [{
192
+ args: [{ selector: 'gbt-app-shell', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-app-shell\">\n <a class=\"gbt-app-shell__skip\" [href]=\"'#' + mainId\">{{ skipLabel() }}</a>\n\n <nav\n #nav\n [id]=\"navId\"\n class=\"gbt-app-shell__nav\"\n [class.gbt-app-shell__nav--open]=\"menuOpen()\"\n [class.gbt-app-shell__nav--collapsed]=\"collapsed()\"\n [attr.aria-label]=\"navLabel()\"\n tabindex=\"-1\"\n (keydown)=\"onNavKeydown($event)\"\n >\n <div class=\"gbt-app-shell__brand\">\n <ng-content select=\"[shell-brand]\" />\n </div>\n <ng-content select=\"[shell-nav]\" />\n @if (collapsible()) {\n <button\n type=\"button\"\n class=\"gbt-app-shell__collapse-toggle\"\n [class.gbt-app-shell__collapse-toggle--collapsed]=\"collapsed()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? expandLabel() : collapseLabel()\"\n (click)=\"toggleCollapsed()\"\n >\n <gbt-icon name=\"chevrons-left\" />\n </button>\n }\n </nav>\n\n @if (menuOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-app-shell__scrim\" (click)=\"close()\"></div>\n }\n\n <div class=\"gbt-app-shell__body\">\n <header class=\"gbt-app-shell__header\">\n <button\n #toggle\n type=\"button\"\n class=\"gbt-app-shell__toggle\"\n [attr.aria-expanded]=\"menuOpen()\"\n [attr.aria-controls]=\"navId\"\n [attr.aria-label]=\"menuLabel()\"\n (click)=\"toggleMenu()\"\n >\n <span class=\"gbt-app-shell__burger\" aria-hidden=\"true\"></span>\n </button>\n <ng-content select=\"[shell-header]\" />\n </header>\n\n <main [id]=\"mainId\" class=\"gbt-app-shell__content\" tabindex=\"-1\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-app-shell{display:flex;min-height:100vh;background:var(--bg-panel)}.gbt-app-shell__skip{position:absolute;left:-9999px;top:0;z-index:1040;padding:.5rem .75rem;border-radius:var(--site-border-radius-sm);background:var(--primary);color:var(--text-on-primary);font-size:.875rem;text-decoration:none}.gbt-app-shell__skip:focus-visible{left:.5rem;top:.5rem;outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__nav{display:flex;flex-direction:column;gap:.25rem;flex-shrink:0;box-sizing:border-box;width:220px;padding:1rem .75rem;background:var(--bg-panel);border-right:1px solid var(--border-color);overflow:hidden;transition:width .2s ease}@media(min-width:769px){.gbt-app-shell__nav--collapsed{width:64px}}.gbt-app-shell__brand{display:flex;align-items:center;gap:.625rem;margin-bottom:1rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gbt-app-shell__collapse-toggle{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.625rem;width:100%;margin-top:auto;padding:.5rem .75rem;border:none;border-radius:var(--site-border-radius-sm);background:transparent;color:var(--text-secondary);cursor:pointer}.gbt-app-shell__collapse-toggle:hover{background:var(--bg-hover)}.gbt-app-shell__collapse-toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__collapse-toggle gbt-icon{transition:transform .2s ease}.gbt-app-shell__collapse-toggle--collapsed gbt-icon{transform:rotate(180deg)}.gbt-app-shell__body{display:flex;flex-direction:column;flex:1;min-width:0}.gbt-app-shell__header{position:relative;z-index:1010;display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;border-bottom:1px solid var(--border-color)}.gbt-app-shell__toggle{display:none;flex-shrink:0;width:2.25rem;height:2.25rem;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:transparent;cursor:pointer}.gbt-app-shell__toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-app-shell__burger{display:block;position:relative;width:1rem;height:2px;margin:0 auto;background:var(--text-primary)}.gbt-app-shell__burger:before,.gbt-app-shell__burger:after{content:\"\";position:absolute;left:0;width:100%;height:2px;background:var(--text-primary)}.gbt-app-shell__burger:before{top:-5px}.gbt-app-shell__burger:after{top:5px}.gbt-app-shell__content{flex:1;min-width:0;padding:1rem}.gbt-app-shell__content:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}@media(max-width:768px){.gbt-app-shell__toggle{display:block}.gbt-app-shell__nav{position:fixed;top:0;bottom:0;left:0;z-index:1030;transform:translate(-100%);transition:transform .16s ease-out}}@media(max-width:768px)and (prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}}@media(max-width:768px){.gbt-app-shell__nav--open{transform:translate(0)}.gbt-app-shell__scrim{position:fixed;inset:0;z-index:1020;background:#0006}}@media(prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}.gbt-app-shell__collapse-toggle gbt-icon{transition:none}}\n"] }]
193
+ }], propDecorators: { navLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "navLabel", required: true }] }], skipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLabel", required: true }] }], openMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "openMenuLabel", required: true }] }], closeMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeMenuLabel", required: true }] }], collapseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseLabel", required: false }] }], expandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandLabel", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsedChange: [{ type: i0.Output, args: ["collapsedChange"] }], toggleButton: [{ type: i0.ViewChild, args: ['toggle', { isSignal: true }] }], nav: [{ type: i0.ViewChild, args: ['nav', { isSignal: true }] }], onEscape: [{
166
194
  type: HostListener,
167
195
  args: ['document:keydown.escape']
168
196
  }] } });
@@ -198,23 +226,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
198
226
  args: [{ selector: 'gbt-button', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [type]=\"type()\"\n class=\"gbt-button gbt-button--{{ variant() }} gbt-button--{{ size() }}\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n (click)=\"handleClick()\"\n>\n @if (iconName()) {\n <gbt-icon [name]=\"iconName()!\" aria-hidden=\"true\" />\n }\n @if (loading()) {\n <span class=\"gbt-button__spinner\" aria-hidden=\"true\"></span>\n <span class=\"sr-only\">{{ loadingLabel() }}</span>\n }\n <span>{{ text() }}</span>\n</button>\n", styles: [":host{display:inline-block;width:fit-content}.gbt-button{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;border:none;border-radius:var(--site-border-radius-sm);font-family:var(--font-family);font-weight:600;cursor:pointer;transition:background-color var(--site-transition-fast),opacity var(--site-transition-fast)}.gbt-button:disabled{cursor:not-allowed;opacity:.5}.gbt-button--small{padding:.375rem .75rem;font-size:.8125rem}.gbt-button--medium{padding:.5rem 1rem;font-size:.875rem}.gbt-button--large{padding:.75rem 1.5rem;font-size:1rem}.gbt-button--primary{background:var(--primary);color:var(--text-on-primary)}.gbt-button--primary:not(:disabled):hover{background:var(--primary-hover)}.gbt-button--secondary{background:var(--bg-panel);color:var(--text-primary);border:1px solid var(--border-color)}.gbt-button--secondary:not(:disabled):hover{background:var(--bg-hover)}.gbt-button--danger{background:var(--color-error-fill);color:var(--text-on-error)}.gbt-button--danger:not(:disabled):hover{background:var(--color-error-hover)}.gbt-button__spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:gbt-button-spin .6s linear infinite}@media(prefers-reduced-motion:reduce){.gbt-button__spinner{animation:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@keyframes gbt-button-spin{to{transform:rotate(360deg)}}\n"] }]
199
227
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
200
228
 
201
- class Card {
202
- hoverable = input(false, { ...(ngDevMode ? { debugName: "hoverable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
203
- heading = input('', /* @ts-ignore */
229
+ class Badge {
230
+ variant = input('neutral', /* @ts-ignore */
231
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
232
+ icon = input(/* @ts-ignore */
233
+ ...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
234
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Badge, deps: [], target: i0.ɵɵFactoryTarget.Component });
235
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Badge, isStandalone: true, selector: "gbt-badge", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<span class=\"gbt-badge\" [attr.data-variant]=\"variant()\">\n @if (icon(); as name) {\n <gbt-icon [name]=\"name\" class=\"gbt-badge__icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-badge__label\"><ng-content /></span>\n</span>\n", styles: [":host{display:inline-flex}.gbt-badge{box-sizing:border-box;display:inline-flex;align-items:center;gap:.25rem;padding:.125rem .5rem;border-radius:999px;background:var(--bg-hover);color:var(--text-secondary);font-size:.75rem;font-weight:600;line-height:1.4;white-space:nowrap}.gbt-badge[data-variant=success]{background:var(--color-success-bg);color:var(--color-success-bg-text)}.gbt-badge[data-variant=warning]{background:var(--color-warning-bg);color:var(--color-warning-bg-text)}.gbt-badge[data-variant=error]{background:var(--color-error-bg);color:var(--color-error-bg-text)}.gbt-badge[data-variant=info]{background:var(--color-info-bg);color:var(--color-info-bg-text)}.gbt-badge__icon{flex-shrink:0;width:.875em;height:.875em}.gbt-badge__label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
236
+ }
237
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Badge, decorators: [{
238
+ type: Component,
239
+ args: [{ selector: 'gbt-badge', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"gbt-badge\" [attr.data-variant]=\"variant()\">\n @if (icon(); as name) {\n <gbt-icon [name]=\"name\" class=\"gbt-badge__icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-badge__label\"><ng-content /></span>\n</span>\n", styles: [":host{display:inline-flex}.gbt-badge{box-sizing:border-box;display:inline-flex;align-items:center;gap:.25rem;padding:.125rem .5rem;border-radius:999px;background:var(--bg-hover);color:var(--text-secondary);font-size:.75rem;font-weight:600;line-height:1.4;white-space:nowrap}.gbt-badge[data-variant=success]{background:var(--color-success-bg);color:var(--color-success-bg-text)}.gbt-badge[data-variant=warning]{background:var(--color-warning-bg);color:var(--color-warning-bg-text)}.gbt-badge[data-variant=error]{background:var(--color-error-bg);color:var(--color-error-bg-text)}.gbt-badge[data-variant=info]{background:var(--color-info-bg);color:var(--color-info-bg-text)}.gbt-badge__icon{flex-shrink:0;width:.875em;height:.875em}.gbt-badge__label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"] }]
240
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
241
+
242
+ class EmptyState {
243
+ illustration = input.required(/* @ts-ignore */
244
+ ...(ngDevMode ? [{ debugName: "illustration" }] : /* istanbul ignore next */ []));
245
+ heading = input.required(/* @ts-ignore */
204
246
  ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
205
- icon = input('', /* @ts-ignore */
206
- ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
207
- headingLevel = input(2, /* @ts-ignore */
208
- ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
209
- cardClass = computed(() => 'gbt-card' + (this.hoverable() ? ' gbt-card--hoverable' : ''), /* @ts-ignore */
210
- ...(ngDevMode ? [{ debugName: "cardClass" }] : /* istanbul ignore next */ []));
211
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Card, deps: [], target: i0.ɵɵFactoryTarget.Component });
212
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Card, isStandalone: true, selector: "gbt-card", inputs: { hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"cardClass()\">\n @if (heading()) {\n <div class=\"gbt-card__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h1>\n }\n @case (3) {\n <h3 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h3>\n }\n @case (4) {\n <h4 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h4>\n }\n @case (5) {\n <h5 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h5>\n }\n @case (6) {\n <h6 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h6>\n }\n @default {\n <h2 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h2>\n }\n }\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n }\n <ng-content></ng-content>\n</div>\n<ng-template #headingContent>\n @if (icon()) {\n <gbt-icon [name]=\"icon()\" aria-hidden=\"true\" />\n }\n {{ heading() }}\n</ng-template>\n", styles: [":host{display:block}.gbt-card{background:var(--bg-principal);border-radius:var(--site-border-radius-lg);box-shadow:var(--site-shadow-sm);position:relative;overflow:hidden;transition:box-shadow .18s cubic-bezier(.4,0,.2,1);padding:1.25rem 1.5rem;font-size:.9rem;line-height:1.65;color:var(--text-secondary)}.gbt-card--hoverable{cursor:pointer;-webkit-user-select:none;user-select:none}.gbt-card--hoverable:hover{box-shadow:var(--site-shadow-lg)}.gbt-card__header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:.75rem}.gbt-card__title{display:flex;align-items:center;gap:.5rem;font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
247
+ message = input('', /* @ts-ignore */
248
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
249
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EmptyState, deps: [], target: i0.ɵɵFactoryTarget.Component });
250
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: EmptyState, isStandalone: true, selector: "gbt-empty-state", inputs: { illustration: { classPropertyName: "illustration", publicName: "illustration", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"gbt-empty-state\">\n <div class=\"gbt-empty-state__illustration\" aria-hidden=\"true\">\n @switch (illustration()) {\n @case ('folder') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"16\" y=\"38\" width=\"64\" height=\"40\" rx=\"4\" />\n <path d=\"M16 38 v-8a4 4 0 0 1 4-4h16l8 8h28a4 4 0 0 1 4 4\" />\n <rect x=\"34\" y=\"14\" width=\"16\" height=\"20\" rx=\"2\" transform=\"rotate(-8 42 24)\" opacity=\"0.55\" />\n <rect x=\"50\" y=\"16\" width=\"16\" height=\"20\" rx=\"2\" transform=\"rotate(6 58 26)\" opacity=\"0.55\" />\n </svg>\n }\n @case ('star') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M48,18 L55.6,37.5 L76.5,38.7 L60.4,52 L65.6,72.3 L48,61 L30.4,72.3 L35.6,52 L19.5,38.7 L40.4,37.5 Z\" />\n <path d=\"M78,14 L81,20 L78,26 L75,20 Z\" opacity=\"0.55\" />\n <path d=\"M16,64 L19,70 L16,76 L13,70 Z\" opacity=\"0.55\" />\n </svg>\n }\n @case ('checklist') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"24\" y=\"18\" width=\"48\" height=\"64\" rx=\"6\" />\n <rect x=\"38\" y=\"12\" width=\"20\" height=\"10\" rx=\"3\" />\n <line x1=\"34\" y1=\"38\" x2=\"62\" y2=\"38\" />\n <path d=\"M32 50 l4 4 l8-8\" />\n <line x1=\"46\" y1=\"52\" x2=\"62\" y2=\"52\" />\n <line x1=\"34\" y1=\"66\" x2=\"62\" y2=\"66\" opacity=\"0.55\" />\n </svg>\n }\n @case ('merge') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"26\" cy=\"20\" r=\"7\" />\n <circle cx=\"26\" cy=\"76\" r=\"7\" />\n <circle cx=\"70\" cy=\"48\" r=\"7\" />\n <path d=\"M26 27 V60 Q26 68 34 68 H63\" />\n <path d=\"M26 55 Q26 41 40 41 H63\" />\n </svg>\n }\n @case ('pipeline') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"18\" cy=\"48\" r=\"10\" />\n <path d=\"M14 42 L25 48 L14 54 Z\" fill=\"currentColor\" stroke=\"none\" />\n <line x1=\"28\" y1=\"48\" x2=\"42\" y2=\"48\" />\n <circle cx=\"50\" cy=\"48\" r=\"8\" />\n <line x1=\"58\" y1=\"48\" x2=\"72\" y2=\"48\" />\n <circle cx=\"80\" cy=\"48\" r=\"8\" />\n </svg>\n }\n @case ('tag') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 20 H54 L82 48 L54 76 H18 Q14 76 14 72 V24 Q14 20 18 20 Z\" />\n <circle cx=\"34\" cy=\"36\" r=\"5\" />\n </svg>\n }\n @case ('book') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M48 26 Q34 16 16 20 V72 Q34 68 48 78 Q62 68 80 72 V20 Q62 16 48 26 Z\" />\n <line x1=\"24\" y1=\"32\" x2=\"40\" y2=\"30\" />\n <line x1=\"24\" y1=\"42\" x2=\"40\" y2=\"40\" />\n <line x1=\"56\" y1=\"30\" x2=\"72\" y2=\"32\" />\n <line x1=\"56\" y1=\"40\" x2=\"72\" y2=\"42\" />\n </svg>\n }\n }\n </div>\n <p class=\"gbt-empty-state__heading\">{{ heading() }}</p>\n @if (message()) {\n <p class=\"gbt-empty-state__message\">{{ message() }}</p>\n }\n <div class=\"gbt-empty-state__action\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block}.gbt-empty-state{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.75rem;padding:3rem 1.5rem}.gbt-empty-state__illustration{width:6rem;height:6rem;color:var(--text-discret)}.gbt-empty-state__illustration svg{width:100%;height:100%}.gbt-empty-state__heading{margin:0;font-size:1rem;font-weight:600;color:var(--text-primary)}.gbt-empty-state__message{margin:0;max-width:32rem;color:var(--text-secondary);font-size:.875rem}.gbt-empty-state__action:empty{display:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
213
251
  }
214
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Card, decorators: [{
252
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EmptyState, decorators: [{
215
253
  type: Component,
216
- args: [{ selector: 'gbt-card', standalone: true, imports: [Icon, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"cardClass()\">\n @if (heading()) {\n <div class=\"gbt-card__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h1>\n }\n @case (3) {\n <h3 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h3>\n }\n @case (4) {\n <h4 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h4>\n }\n @case (5) {\n <h5 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h5>\n }\n @case (6) {\n <h6 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h6>\n }\n @default {\n <h2 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h2>\n }\n }\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n }\n <ng-content></ng-content>\n</div>\n<ng-template #headingContent>\n @if (icon()) {\n <gbt-icon [name]=\"icon()\" aria-hidden=\"true\" />\n }\n {{ heading() }}\n</ng-template>\n", styles: [":host{display:block}.gbt-card{background:var(--bg-principal);border-radius:var(--site-border-radius-lg);box-shadow:var(--site-shadow-sm);position:relative;overflow:hidden;transition:box-shadow .18s cubic-bezier(.4,0,.2,1);padding:1.25rem 1.5rem;font-size:.9rem;line-height:1.65;color:var(--text-secondary)}.gbt-card--hoverable{cursor:pointer;-webkit-user-select:none;user-select:none}.gbt-card--hoverable:hover{box-shadow:var(--site-shadow-lg)}.gbt-card__header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:.75rem}.gbt-card__title{display:flex;align-items:center;gap:.5rem;font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}\n"] }]
217
- }], propDecorators: { hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }] } });
254
+ args: [{ selector: 'gbt-empty-state', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-empty-state\">\n <div class=\"gbt-empty-state__illustration\" aria-hidden=\"true\">\n @switch (illustration()) {\n @case ('folder') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"16\" y=\"38\" width=\"64\" height=\"40\" rx=\"4\" />\n <path d=\"M16 38 v-8a4 4 0 0 1 4-4h16l8 8h28a4 4 0 0 1 4 4\" />\n <rect x=\"34\" y=\"14\" width=\"16\" height=\"20\" rx=\"2\" transform=\"rotate(-8 42 24)\" opacity=\"0.55\" />\n <rect x=\"50\" y=\"16\" width=\"16\" height=\"20\" rx=\"2\" transform=\"rotate(6 58 26)\" opacity=\"0.55\" />\n </svg>\n }\n @case ('star') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M48,18 L55.6,37.5 L76.5,38.7 L60.4,52 L65.6,72.3 L48,61 L30.4,72.3 L35.6,52 L19.5,38.7 L40.4,37.5 Z\" />\n <path d=\"M78,14 L81,20 L78,26 L75,20 Z\" opacity=\"0.55\" />\n <path d=\"M16,64 L19,70 L16,76 L13,70 Z\" opacity=\"0.55\" />\n </svg>\n }\n @case ('checklist') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"24\" y=\"18\" width=\"48\" height=\"64\" rx=\"6\" />\n <rect x=\"38\" y=\"12\" width=\"20\" height=\"10\" rx=\"3\" />\n <line x1=\"34\" y1=\"38\" x2=\"62\" y2=\"38\" />\n <path d=\"M32 50 l4 4 l8-8\" />\n <line x1=\"46\" y1=\"52\" x2=\"62\" y2=\"52\" />\n <line x1=\"34\" y1=\"66\" x2=\"62\" y2=\"66\" opacity=\"0.55\" />\n </svg>\n }\n @case ('merge') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"26\" cy=\"20\" r=\"7\" />\n <circle cx=\"26\" cy=\"76\" r=\"7\" />\n <circle cx=\"70\" cy=\"48\" r=\"7\" />\n <path d=\"M26 27 V60 Q26 68 34 68 H63\" />\n <path d=\"M26 55 Q26 41 40 41 H63\" />\n </svg>\n }\n @case ('pipeline') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"18\" cy=\"48\" r=\"10\" />\n <path d=\"M14 42 L25 48 L14 54 Z\" fill=\"currentColor\" stroke=\"none\" />\n <line x1=\"28\" y1=\"48\" x2=\"42\" y2=\"48\" />\n <circle cx=\"50\" cy=\"48\" r=\"8\" />\n <line x1=\"58\" y1=\"48\" x2=\"72\" y2=\"48\" />\n <circle cx=\"80\" cy=\"48\" r=\"8\" />\n </svg>\n }\n @case ('tag') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 20 H54 L82 48 L54 76 H18 Q14 76 14 72 V24 Q14 20 18 20 Z\" />\n <circle cx=\"34\" cy=\"36\" r=\"5\" />\n </svg>\n }\n @case ('book') {\n <svg viewBox=\"0 0 96 96\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M48 26 Q34 16 16 20 V72 Q34 68 48 78 Q62 68 80 72 V20 Q62 16 48 26 Z\" />\n <line x1=\"24\" y1=\"32\" x2=\"40\" y2=\"30\" />\n <line x1=\"24\" y1=\"42\" x2=\"40\" y2=\"40\" />\n <line x1=\"56\" y1=\"30\" x2=\"72\" y2=\"32\" />\n <line x1=\"56\" y1=\"40\" x2=\"72\" y2=\"42\" />\n </svg>\n }\n }\n </div>\n <p class=\"gbt-empty-state__heading\">{{ heading() }}</p>\n @if (message()) {\n <p class=\"gbt-empty-state__message\">{{ message() }}</p>\n }\n <div class=\"gbt-empty-state__action\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block}.gbt-empty-state{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.75rem;padding:3rem 1.5rem}.gbt-empty-state__illustration{width:6rem;height:6rem;color:var(--text-discret)}.gbt-empty-state__illustration svg{width:100%;height:100%}.gbt-empty-state__heading{margin:0;font-size:1rem;font-weight:600;color:var(--text-primary)}.gbt-empty-state__message{margin:0;max-width:32rem;color:var(--text-secondary);font-size:.875rem}.gbt-empty-state__action:empty{display:none}\n"] }]
255
+ }], propDecorators: { illustration: [{ type: i0.Input, args: [{ isSignal: true, alias: "illustration", required: true }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }] } });
218
256
 
219
257
  let nextInputId = 0;
220
258
  class GbtInput {
@@ -285,7 +323,7 @@ class GbtInput {
285
323
  useExisting: forwardRef(() => GbtInput),
286
324
  multi: true,
287
325
  },
288
- ], ngImport: i0, template: "<div class=\"gbt-input\">\n @if (label()) {\n <label [for]=\"id()\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-input__wrapper\">\n <input\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (type() === 'password') {\n <button\n type=\"button\"\n class=\"gbt-input__toggle\"\n (click)=\"togglePasswordVisibility()\"\n [attr.aria-label]=\"passwordVisible() ? hidePasswordLabel() : showPasswordLabel()\"\n >\n <gbt-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{display:block}.gbt-input{display:flex;flex-direction:column;gap:.375rem}.gbt-input label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-input__wrapper{position:relative;display:flex;align-items:center}.gbt-input input{width:100%;padding:.5rem .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-input input:focus{outline:none;border-color:var(--primary)}.gbt-input input:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-input input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-input__toggle{position:absolute;right:.5rem;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-input__toggle:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
326
+ ], ngImport: i0, template: "<div class=\"gbt-input\">\n @if (label()) {\n <label [for]=\"id()\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-input__wrapper\">\n <input\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (type() === 'password') {\n <button\n type=\"button\"\n class=\"gbt-input__toggle\"\n (click)=\"togglePasswordVisibility()\"\n [attr.aria-label]=\"passwordVisible() ? hidePasswordLabel() : showPasswordLabel()\"\n >\n <gbt-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{display:block}.gbt-input{display:flex;flex-direction:column;gap:.375rem}.gbt-input label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-input__wrapper{position:relative;display:flex;align-items:center}.gbt-input input{box-sizing:border-box;width:100%;padding:.5rem .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-input input:focus{outline:none;border-color:var(--primary)}.gbt-input input:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-input input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-input__toggle{position:absolute;right:.5rem;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-input__toggle:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
289
327
  }
290
328
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GbtInput, decorators: [{
291
329
  type: Component,
@@ -295,62 +333,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
295
333
  useExisting: forwardRef(() => GbtInput),
296
334
  multi: true,
297
335
  },
298
- ], template: "<div class=\"gbt-input\">\n @if (label()) {\n <label [for]=\"id()\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-input__wrapper\">\n <input\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (type() === 'password') {\n <button\n type=\"button\"\n class=\"gbt-input__toggle\"\n (click)=\"togglePasswordVisibility()\"\n [attr.aria-label]=\"passwordVisible() ? hidePasswordLabel() : showPasswordLabel()\"\n >\n <gbt-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{display:block}.gbt-input{display:flex;flex-direction:column;gap:.375rem}.gbt-input label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-input__wrapper{position:relative;display:flex;align-items:center}.gbt-input input{width:100%;padding:.5rem .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-input input:focus{outline:none;border-color:var(--primary)}.gbt-input input:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-input input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-input__toggle{position:absolute;right:.5rem;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-input__toggle:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
336
+ ], template: "<div class=\"gbt-input\">\n @if (label()) {\n <label [for]=\"id()\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-input__wrapper\">\n <input\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (type() === 'password') {\n <button\n type=\"button\"\n class=\"gbt-input__toggle\"\n (click)=\"togglePasswordVisibility()\"\n [attr.aria-label]=\"passwordVisible() ? hidePasswordLabel() : showPasswordLabel()\"\n >\n <gbt-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{display:block}.gbt-input{display:flex;flex-direction:column;gap:.375rem}.gbt-input label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-input__wrapper{position:relative;display:flex;align-items:center}.gbt-input input{box-sizing:border-box;width:100%;padding:.5rem .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-input input:focus{outline:none;border-color:var(--primary)}.gbt-input input:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-input input:disabled{background:var(--bg-panel);cursor:not-allowed}.gbt-input__toggle{position:absolute;right:.5rem;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-input__toggle:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
299
337
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], showPasswordLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPasswordLabel", required: false }] }], hidePasswordLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePasswordLabel", required: false }] }], committed: [{ type: i0.Output, args: ["committed"] }] } });
300
338
 
301
- let nextCheckboxId = 0;
302
- class Checkbox {
303
- id = input(`gbt-checkbox-${++nextCheckboxId}`, /* @ts-ignore */
304
- ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
305
- label = input('', /* @ts-ignore */
306
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
307
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
308
- checked = signal(false, /* @ts-ignore */
309
- ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
310
- formDisabled = signal(false, /* @ts-ignore */
311
- ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
312
- isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
313
- ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
314
- onChange = () => { };
315
- onTouched = () => { };
316
- writeValue(value) {
317
- this.checked.set(!!value);
318
- }
319
- registerOnChange(fn) {
320
- this.onChange = fn;
321
- }
322
- registerOnTouched(fn) {
323
- this.onTouched = fn;
324
- }
325
- setDisabledState(isDisabled) {
326
- this.formDisabled.set(isDisabled);
327
- }
328
- onToggle(event) {
329
- const value = event.target.checked;
330
- this.checked.set(value);
331
- this.onChange(value);
332
- this.onTouched();
333
- }
334
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Checkbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
335
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: Checkbox, isStandalone: true, selector: "gbt-checkbox", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
336
- {
337
- provide: NG_VALUE_ACCESSOR,
338
- useExisting: forwardRef(() => Checkbox),
339
- multi: true,
340
- },
341
- ], ngImport: i0, template: "<label class=\"gbt-checkbox\" [class.gbt-checkbox--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-checkbox{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-checkbox:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-checkbox--disabled{cursor:not-allowed;opacity:.5}.gbt-checkbox input{width:1rem;height:1rem;accent-color:var(--primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
342
- }
343
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Checkbox, decorators: [{
344
- type: Component,
345
- args: [{ selector: 'gbt-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
346
- {
347
- provide: NG_VALUE_ACCESSOR,
348
- useExisting: forwardRef(() => Checkbox),
349
- multi: true,
350
- },
351
- ], template: "<label class=\"gbt-checkbox\" [class.gbt-checkbox--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-checkbox{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-checkbox:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-checkbox--disabled{cursor:not-allowed;opacity:.5}.gbt-checkbox input{width:1rem;height:1rem;accent-color:var(--primary)}\n"] }]
352
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
353
-
354
339
  let nextSelectId = 0;
355
340
  class Select {
356
341
  elementRef = inject(ElementRef);
@@ -358,6 +343,8 @@ class Select {
358
343
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
359
344
  label = input('', /* @ts-ignore */
360
345
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
346
+ size = input('md', /* @ts-ignore */
347
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
361
348
  options = input.required(/* @ts-ignore */
362
349
  ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
363
350
  multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -517,13 +504,13 @@ class Select {
517
504
  }
518
505
  }
519
506
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component });
520
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Select, isStandalone: true, selector: "gbt-select", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, selectedCountLabel: { classPropertyName: "selectedCountLabel", publicName: "selectedCountLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "handleClickOutside($event)", "keydown": "onKeydown($event)", "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" } }, providers: [
507
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Select, isStandalone: true, selector: "gbt-select", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, selectedCountLabel: { classPropertyName: "selectedCountLabel", publicName: "selectedCountLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "handleClickOutside($event)", "keydown": "onKeydown($event)", "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" }, properties: { "class.gbt-select--sm": "size() === 'sm'" } }, providers: [
521
508
  {
522
509
  provide: NG_VALUE_ACCESSOR,
523
510
  useExisting: forwardRef(() => Select),
524
511
  multi: true,
525
512
  },
526
- ], ngImport: i0, template: "<div class=\"gbt-select\" [class.gbt-select--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [id]=\"labelId()\" [for]=\"id()\" class=\"gbt-select__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-select__trigger\"\n [class.gbt-select__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\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-labelledby]=\"label() ? labelId() + ' ' + id() : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" class=\"gbt-select__trigger-icon\" aria-hidden=\"true\" />\n }\n <span\n class=\"gbt-select__trigger-label\"\n [class.gbt-select__trigger-label--placeholder]=\"selectedOptions().length === 0\"\n >\n {{ triggerLabel() }}\n </span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-select__chevron\" aria-hidden=\"true\" />\n </button>\n @if (open() && panelStyle(); as style) {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-select__panel\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n [attr.aria-multiselectable]=\"multiple()\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n >\n @for (option of options(); track option.value; 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-select__option\"\n [class.gbt-select__option--selected]=\"isSelected(option.value)\"\n [class.gbt-select__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"isSelected(option.value)\"\n (click)=\"selectOption(option.value)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (option.icon) {\n <gbt-icon [name]=\"option.icon\" class=\"gbt-select__option-icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option.value)) {\n <gbt-icon name=\"check\" class=\"gbt-select__option-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-select__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{position:relative;display:inline-block;min-width:180px}.gbt-select{display:flex;flex-direction:column;gap:.375rem}.gbt-select--disabled{opacity:.5}.gbt-select__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-select__trigger{display:flex;align-items:center;gap:8px;width:100%;height:40px;padding:0 10px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:14px;cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),box-shadow .15s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger:hover:not(:disabled){border-color:var(--border-color)}.gbt-select__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-select__trigger:disabled{cursor:not-allowed}.gbt-select__trigger-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__trigger-label{flex:1;min-width:0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__trigger-label--placeholder{color:var(--text-discret)}.gbt-select__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger--open .gbt-select__chevron{transform:rotate(180deg)}.gbt-select__panel{position:fixed;z-index:1000;margin:0;padding:6px;list-style:none;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-select-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-select__panel::-webkit-scrollbar{width:6px}.gbt-select__panel::-webkit-scrollbar-track{background:transparent}.gbt-select__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-select__option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:8px;color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-select__option:hover,.gbt-select__option--active{background:var(--bg-hover)}.gbt-select__option--selected{color:var(--primary);font-weight:600}.gbt-select__option-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__option--selected .gbt-select__option-icon{color:var(--primary)}.gbt-select__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__option-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-select-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-select__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-select__panel{animation:none}.gbt-select__chevron{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
513
+ ], ngImport: i0, template: "<div class=\"gbt-select\" [class.gbt-select--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [id]=\"labelId()\" [for]=\"id()\" class=\"gbt-select__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-select__trigger\"\n [class.gbt-select__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\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-labelledby]=\"label() ? labelId() + ' ' + id() : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" class=\"gbt-select__trigger-icon\" aria-hidden=\"true\" />\n }\n <span\n class=\"gbt-select__trigger-label\"\n [class.gbt-select__trigger-label--placeholder]=\"selectedOptions().length === 0\"\n >\n {{ triggerLabel() }}\n </span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-select__chevron\" aria-hidden=\"true\" />\n </button>\n @if (open() && panelStyle(); as style) {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-select__panel\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n [attr.aria-multiselectable]=\"multiple()\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n >\n @for (option of options(); track option.value; 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-select__option\"\n [class.gbt-select__option--selected]=\"isSelected(option.value)\"\n [class.gbt-select__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"isSelected(option.value)\"\n (click)=\"selectOption(option.value)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (option.icon) {\n <gbt-icon [name]=\"option.icon\" class=\"gbt-select__option-icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option.value)) {\n <gbt-icon name=\"check\" class=\"gbt-select__option-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-select__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{position:relative;display:inline-block;min-width:180px}.gbt-select{display:flex;flex-direction:column;gap:.375rem}.gbt-select--disabled{opacity:.5}.gbt-select__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-select__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;height:40px;padding:0 10px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:14px;cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),box-shadow .15s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger:hover:not(:disabled){border-color:var(--border-color)}.gbt-select__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-select__trigger:disabled{cursor:not-allowed}:host(.gbt-select--sm){min-width:120px}:host(.gbt-select--sm) .gbt-select__trigger{height:32px;padding:0 8px;font-size:13px}.gbt-select__trigger-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__trigger-label{flex:1;min-width:0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__trigger-label--placeholder{color:var(--text-discret)}.gbt-select__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger--open .gbt-select__chevron{transform:rotate(180deg)}.gbt-select__panel{position:fixed;z-index:1000;margin:0;padding:6px;list-style:none;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-select-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-select__panel::-webkit-scrollbar{width:6px}.gbt-select__panel::-webkit-scrollbar-track{background:transparent}.gbt-select__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-select__option{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:8px;color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-select__option:hover,.gbt-select__option--active{background:var(--bg-hover)}.gbt-select__option--selected{color:var(--primary);font-weight:600}.gbt-select__option-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__option--selected .gbt-select__option-icon{color:var(--primary)}.gbt-select__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__option-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-select-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-select__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-select__panel{animation:none}.gbt-select__chevron{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
527
514
  }
528
515
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Select, decorators: [{
529
516
  type: Component,
@@ -532,14 +519,140 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
532
519
  '(keydown)': 'onKeydown($event)',
533
520
  '(window:scroll)': 'updatePanelPosition()',
534
521
  '(window:resize)': 'updatePanelPosition()',
522
+ '[class.gbt-select--sm]': "size() === 'sm'",
535
523
  }, providers: [
536
524
  {
537
525
  provide: NG_VALUE_ACCESSOR,
538
526
  useExisting: forwardRef(() => Select),
539
527
  multi: true,
540
528
  },
541
- ], template: "<div class=\"gbt-select\" [class.gbt-select--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [id]=\"labelId()\" [for]=\"id()\" class=\"gbt-select__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-select__trigger\"\n [class.gbt-select__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\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-labelledby]=\"label() ? labelId() + ' ' + id() : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" class=\"gbt-select__trigger-icon\" aria-hidden=\"true\" />\n }\n <span\n class=\"gbt-select__trigger-label\"\n [class.gbt-select__trigger-label--placeholder]=\"selectedOptions().length === 0\"\n >\n {{ triggerLabel() }}\n </span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-select__chevron\" aria-hidden=\"true\" />\n </button>\n @if (open() && panelStyle(); as style) {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-select__panel\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n [attr.aria-multiselectable]=\"multiple()\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n >\n @for (option of options(); track option.value; 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-select__option\"\n [class.gbt-select__option--selected]=\"isSelected(option.value)\"\n [class.gbt-select__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"isSelected(option.value)\"\n (click)=\"selectOption(option.value)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (option.icon) {\n <gbt-icon [name]=\"option.icon\" class=\"gbt-select__option-icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option.value)) {\n <gbt-icon name=\"check\" class=\"gbt-select__option-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-select__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{position:relative;display:inline-block;min-width:180px}.gbt-select{display:flex;flex-direction:column;gap:.375rem}.gbt-select--disabled{opacity:.5}.gbt-select__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-select__trigger{display:flex;align-items:center;gap:8px;width:100%;height:40px;padding:0 10px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:14px;cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),box-shadow .15s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger:hover:not(:disabled){border-color:var(--border-color)}.gbt-select__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-select__trigger:disabled{cursor:not-allowed}.gbt-select__trigger-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__trigger-label{flex:1;min-width:0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__trigger-label--placeholder{color:var(--text-discret)}.gbt-select__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger--open .gbt-select__chevron{transform:rotate(180deg)}.gbt-select__panel{position:fixed;z-index:1000;margin:0;padding:6px;list-style:none;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-select-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-select__panel::-webkit-scrollbar{width:6px}.gbt-select__panel::-webkit-scrollbar-track{background:transparent}.gbt-select__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-select__option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:8px;color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-select__option:hover,.gbt-select__option--active{background:var(--bg-hover)}.gbt-select__option--selected{color:var(--primary);font-weight:600}.gbt-select__option-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__option--selected .gbt-select__option-icon{color:var(--primary)}.gbt-select__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__option-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-select-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-select__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-select__panel{animation:none}.gbt-select__chevron{transition:none}}\n"] }]
542
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], selectedCountLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedCountLabel", required: false }] }] } });
529
+ ], template: "<div class=\"gbt-select\" [class.gbt-select--disabled]=\"isDisabled()\">\n @if (label()) {\n <label [id]=\"labelId()\" [for]=\"id()\" class=\"gbt-select__label\"\n >{{ label() }}{{ required() ? ' *' : '' }}</label\n >\n }\n\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-select__trigger\"\n [class.gbt-select__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\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-labelledby]=\"label() ? labelId() + ' ' + id() : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" class=\"gbt-select__trigger-icon\" aria-hidden=\"true\" />\n }\n <span\n class=\"gbt-select__trigger-label\"\n [class.gbt-select__trigger-label--placeholder]=\"selectedOptions().length === 0\"\n >\n {{ triggerLabel() }}\n </span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-select__chevron\" aria-hidden=\"true\" />\n </button>\n @if (open() && panelStyle(); as style) {\n <ul\n [id]=\"id() + '-listbox'\"\n class=\"gbt-select__panel\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || placeholder()\"\n [attr.aria-multiselectable]=\"multiple()\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n [style.width]=\"style.width\"\n >\n @for (option of options(); track option.value; 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-select__option\"\n [class.gbt-select__option--selected]=\"isSelected(option.value)\"\n [class.gbt-select__option--active]=\"i === activeIndex()\"\n [attr.aria-selected]=\"isSelected(option.value)\"\n (click)=\"selectOption(option.value)\"\n (mouseenter)=\"activeIndex.set(i)\"\n >\n @if (option.icon) {\n <gbt-icon [name]=\"option.icon\" class=\"gbt-select__option-icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option.value)) {\n <gbt-icon name=\"check\" class=\"gbt-select__option-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-select__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{position:relative;display:inline-block;min-width:180px}.gbt-select{display:flex;flex-direction:column;gap:.375rem}.gbt-select--disabled{opacity:.5}.gbt-select__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-select__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;height:40px;padding:0 10px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:14px;cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),box-shadow .15s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger:hover:not(:disabled){border-color:var(--border-color)}.gbt-select__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-select__trigger:disabled{cursor:not-allowed}:host(.gbt-select--sm){min-width:120px}:host(.gbt-select--sm) .gbt-select__trigger{height:32px;padding:0 8px;font-size:13px}.gbt-select__trigger-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__trigger-label{flex:1;min-width:0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__trigger-label--placeholder{color:var(--text-discret)}.gbt-select__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-select__trigger--open .gbt-select__chevron{transform:rotate(180deg)}.gbt-select__panel{position:fixed;z-index:1000;margin:0;padding:6px;list-style:none;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-select-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-select__panel::-webkit-scrollbar{width:6px}.gbt-select__panel::-webkit-scrollbar-track{background:transparent}.gbt-select__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-select__option{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:8px;color:var(--text-primary);font-size:14px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-select__option:hover,.gbt-select__option--active{background:var(--bg-hover)}.gbt-select__option--selected{color:var(--primary);font-weight:600}.gbt-select__option-icon{flex-shrink:0;color:var(--text-secondary)}.gbt-select__option--selected .gbt-select__option-icon{color:var(--primary)}.gbt-select__option-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-select__option-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-select-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.gbt-select__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-select__panel{animation:none}.gbt-select__chevron{transition:none}}\n"] }]
530
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], selectedCountLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedCountLabel", required: false }] }] } });
531
+
532
+ class ListToolbar {
533
+ searchValue = input('', /* @ts-ignore */
534
+ ...(ngDevMode ? [{ debugName: "searchValue" }] : /* istanbul ignore next */ []));
535
+ searchLabel = input.required(/* @ts-ignore */
536
+ ...(ngDevMode ? [{ debugName: "searchLabel" }] : /* istanbul ignore next */ []));
537
+ searchPlaceholder = input('', /* @ts-ignore */
538
+ ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
539
+ sortOptions = input.required(/* @ts-ignore */
540
+ ...(ngDevMode ? [{ debugName: "sortOptions" }] : /* istanbul ignore next */ []));
541
+ sortValue = input.required(/* @ts-ignore */
542
+ ...(ngDevMode ? [{ debugName: "sortValue" }] : /* istanbul ignore next */ []));
543
+ sortDirection = input('asc', /* @ts-ignore */
544
+ ...(ngDevMode ? [{ debugName: "sortDirection" }] : /* istanbul ignore next */ []));
545
+ sortLabel = input('Sort by', /* @ts-ignore */
546
+ ...(ngDevMode ? [{ debugName: "sortLabel" }] : /* istanbul ignore next */ []));
547
+ directionLabel = input('Reverse sort direction', /* @ts-ignore */
548
+ ...(ngDevMode ? [{ debugName: "directionLabel" }] : /* istanbul ignore next */ []));
549
+ searchValueChange = output();
550
+ sortValueChange = output();
551
+ sortDirectionChange = output();
552
+ // Plain `[ngModel]` bindings on the child `gbt-input`/`gbt-select` defer their
553
+ // initial value to a control-value-accessor writeValue() call scheduled on a
554
+ // microtask (an Angular Forms `NgModel` implementation detail), so the very
555
+ // first render would briefly show the empty/placeholder state. Reactive
556
+ // FormControls propagate `setValue()` to the CVA synchronously, so we mirror
557
+ // the inputs onto internal controls instead and forward user edits back out.
558
+ searchControl = new FormControl('', { nonNullable: true });
559
+ sortControl = new FormControl(null);
560
+ constructor() {
561
+ effect(() => this.searchControl.setValue(this.searchValue(), { emitEvent: false }));
562
+ effect(() => this.sortControl.setValue(this.sortValue(), { emitEvent: false }));
563
+ this.searchControl.valueChanges
564
+ .pipe(takeUntilDestroyed())
565
+ .subscribe((value) => this.searchValueChange.emit(value));
566
+ this.sortControl.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
567
+ if (value !== null && value !== this.sortValue()) {
568
+ this.sortValueChange.emit(value);
569
+ }
570
+ });
571
+ }
572
+ asSelectOptions(options) {
573
+ return options;
574
+ }
575
+ toggleDirection() {
576
+ this.sortDirectionChange.emit(this.sortDirection() === 'asc' ? 'desc' : 'asc');
577
+ }
578
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ListToolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
579
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: ListToolbar, isStandalone: true, selector: "gbt-list-toolbar", inputs: { searchValue: { classPropertyName: "searchValue", publicName: "searchValue", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: true, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, sortOptions: { classPropertyName: "sortOptions", publicName: "sortOptions", isSignal: true, isRequired: true, transformFunction: null }, sortValue: { classPropertyName: "sortValue", publicName: "sortValue", isSignal: true, isRequired: true, transformFunction: null }, sortDirection: { classPropertyName: "sortDirection", publicName: "sortDirection", isSignal: true, isRequired: false, transformFunction: null }, sortLabel: { classPropertyName: "sortLabel", publicName: "sortLabel", isSignal: true, isRequired: false, transformFunction: null }, directionLabel: { classPropertyName: "directionLabel", publicName: "directionLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchValueChange: "searchValueChange", sortValueChange: "sortValueChange", sortDirectionChange: "sortDirectionChange" }, ngImport: i0, template: "<div class=\"gbt-list-toolbar\">\n <gbt-input\n class=\"gbt-list-toolbar__search\"\n [label]=\"searchLabel()\"\n [placeholder]=\"searchPlaceholder()\"\n [formControl]=\"searchControl\"\n />\n <gbt-select\n class=\"gbt-list-toolbar__sort\"\n [label]=\"sortLabel()\"\n [options]=\"asSelectOptions(sortOptions())\"\n [formControl]=\"sortControl\"\n />\n <button\n type=\"button\"\n class=\"gbt-list-toolbar__direction\"\n (click)=\"toggleDirection()\"\n [attr.aria-label]=\"directionLabel()\"\n [attr.aria-pressed]=\"sortDirection() === 'desc'\"\n >\n <gbt-icon [name]=\"sortDirection() === 'asc' ? 'arrow-up' : 'arrow-down'\" />\n </button>\n</div>\n", styles: [":host{display:block}.gbt-list-toolbar{display:flex;align-items:flex-end;gap:.75rem;flex-wrap:wrap}.gbt-list-toolbar__search{flex:1;min-width:200px}.gbt-list-toolbar__sort{min-width:160px}.gbt-list-toolbar__direction{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;flex-shrink:0;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:var(--bg-principal);color:var(--text-secondary);cursor:pointer;transition:background var(--site-transition-fast)}.gbt-list-toolbar__direction:hover{background:var(--bg-hover)}.gbt-list-toolbar__direction:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: GbtInput, selector: "gbt-input", inputs: ["id", "label", "type", "required", "disabled", "placeholder", "errorMessage", "autocomplete", "showPasswordLabel", "hidePasswordLabel"], outputs: ["committed"] }, { kind: "component", type: Select, selector: "gbt-select", inputs: ["id", "label", "size", "options", "multiple", "placeholder", "disabled", "required", "errorMessage", "selectedCountLabel"] }, { kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
580
+ }
581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ListToolbar, decorators: [{
582
+ type: Component,
583
+ args: [{ selector: 'gbt-list-toolbar', standalone: true, imports: [ReactiveFormsModule, GbtInput, Select, Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-list-toolbar\">\n <gbt-input\n class=\"gbt-list-toolbar__search\"\n [label]=\"searchLabel()\"\n [placeholder]=\"searchPlaceholder()\"\n [formControl]=\"searchControl\"\n />\n <gbt-select\n class=\"gbt-list-toolbar__sort\"\n [label]=\"sortLabel()\"\n [options]=\"asSelectOptions(sortOptions())\"\n [formControl]=\"sortControl\"\n />\n <button\n type=\"button\"\n class=\"gbt-list-toolbar__direction\"\n (click)=\"toggleDirection()\"\n [attr.aria-label]=\"directionLabel()\"\n [attr.aria-pressed]=\"sortDirection() === 'desc'\"\n >\n <gbt-icon [name]=\"sortDirection() === 'asc' ? 'arrow-up' : 'arrow-down'\" />\n </button>\n</div>\n", styles: [":host{display:block}.gbt-list-toolbar{display:flex;align-items:flex-end;gap:.75rem;flex-wrap:wrap}.gbt-list-toolbar__search{flex:1;min-width:200px}.gbt-list-toolbar__sort{min-width:160px}.gbt-list-toolbar__direction{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;flex-shrink:0;padding:0;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);background:var(--bg-principal);color:var(--text-secondary);cursor:pointer;transition:background var(--site-transition-fast)}.gbt-list-toolbar__direction:hover{background:var(--bg-hover)}.gbt-list-toolbar__direction:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"] }]
584
+ }], ctorParameters: () => [], propDecorators: { searchValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchValue", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: true }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], sortOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortOptions", required: true }] }], sortValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortValue", required: true }] }], sortDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDirection", required: false }] }], sortLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortLabel", required: false }] }], directionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "directionLabel", required: false }] }], searchValueChange: [{ type: i0.Output, args: ["searchValueChange"] }], sortValueChange: [{ type: i0.Output, args: ["sortValueChange"] }], sortDirectionChange: [{ type: i0.Output, args: ["sortDirectionChange"] }] } });
585
+
586
+ class Card {
587
+ hoverable = input(false, { ...(ngDevMode ? { debugName: "hoverable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
588
+ heading = input('', /* @ts-ignore */
589
+ ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
590
+ icon = input('', /* @ts-ignore */
591
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
592
+ headingLevel = input(2, /* @ts-ignore */
593
+ ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
594
+ cardClass = computed(() => 'gbt-card' + (this.hoverable() ? ' gbt-card--hoverable' : ''), /* @ts-ignore */
595
+ ...(ngDevMode ? [{ debugName: "cardClass" }] : /* istanbul ignore next */ []));
596
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Card, deps: [], target: i0.ɵɵFactoryTarget.Component });
597
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Card, isStandalone: true, selector: "gbt-card", inputs: { hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"cardClass()\">\n @if (heading()) {\n <div class=\"gbt-card__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h1>\n }\n @case (3) {\n <h3 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h3>\n }\n @case (4) {\n <h4 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h4>\n }\n @case (5) {\n <h5 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h5>\n }\n @case (6) {\n <h6 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h6>\n }\n @default {\n <h2 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h2>\n }\n }\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n }\n <ng-content></ng-content>\n</div>\n<ng-template #headingContent>\n @if (icon()) {\n <gbt-icon [name]=\"icon()\" aria-hidden=\"true\" />\n }\n {{ heading() }}\n</ng-template>\n", styles: [":host{display:block}.gbt-card{background:var(--bg-principal);border-radius:var(--site-border-radius-lg);box-shadow:var(--site-shadow-sm);position:relative;overflow:hidden;transition:box-shadow .18s cubic-bezier(.4,0,.2,1);padding:1.25rem 1.5rem;font-size:.9rem;line-height:1.65;color:var(--text-secondary)}.gbt-card--hoverable{cursor:pointer;-webkit-user-select:none;user-select:none}.gbt-card--hoverable:hover{box-shadow:var(--site-shadow-lg)}.gbt-card__header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:.75rem}.gbt-card__title{display:flex;align-items:center;gap:.5rem;font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
598
+ }
599
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Card, decorators: [{
600
+ type: Component,
601
+ args: [{ selector: 'gbt-card', standalone: true, imports: [Icon, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"cardClass()\">\n @if (heading()) {\n <div class=\"gbt-card__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h1>\n }\n @case (3) {\n <h3 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h3>\n }\n @case (4) {\n <h4 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h4>\n }\n @case (5) {\n <h5 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h5>\n }\n @case (6) {\n <h6 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h6>\n }\n @default {\n <h2 class=\"gbt-card__title\"><ng-container *ngTemplateOutlet=\"headingContent\" /></h2>\n }\n }\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n }\n <ng-content></ng-content>\n</div>\n<ng-template #headingContent>\n @if (icon()) {\n <gbt-icon [name]=\"icon()\" aria-hidden=\"true\" />\n }\n {{ heading() }}\n</ng-template>\n", styles: [":host{display:block}.gbt-card{background:var(--bg-principal);border-radius:var(--site-border-radius-lg);box-shadow:var(--site-shadow-sm);position:relative;overflow:hidden;transition:box-shadow .18s cubic-bezier(.4,0,.2,1);padding:1.25rem 1.5rem;font-size:.9rem;line-height:1.65;color:var(--text-secondary)}.gbt-card--hoverable{cursor:pointer;-webkit-user-select:none;user-select:none}.gbt-card--hoverable:hover{box-shadow:var(--site-shadow-lg)}.gbt-card__header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:.75rem}.gbt-card__title{display:flex;align-items:center;gap:.5rem;font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}\n"] }]
602
+ }], propDecorators: { hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }] } });
603
+
604
+ let nextCheckboxId = 0;
605
+ class Checkbox {
606
+ id = input(`gbt-checkbox-${++nextCheckboxId}`, /* @ts-ignore */
607
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
608
+ label = input('', /* @ts-ignore */
609
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
610
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
611
+ checked = signal(false, /* @ts-ignore */
612
+ ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
613
+ formDisabled = signal(false, /* @ts-ignore */
614
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
615
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
616
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
617
+ onChange = () => { };
618
+ onTouched = () => { };
619
+ writeValue(value) {
620
+ this.checked.set(!!value);
621
+ }
622
+ registerOnChange(fn) {
623
+ this.onChange = fn;
624
+ }
625
+ registerOnTouched(fn) {
626
+ this.onTouched = fn;
627
+ }
628
+ setDisabledState(isDisabled) {
629
+ this.formDisabled.set(isDisabled);
630
+ }
631
+ onToggle(event) {
632
+ const value = event.target.checked;
633
+ this.checked.set(value);
634
+ this.onChange(value);
635
+ this.onTouched();
636
+ }
637
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Checkbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: Checkbox, isStandalone: true, selector: "gbt-checkbox", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
639
+ {
640
+ provide: NG_VALUE_ACCESSOR,
641
+ useExisting: forwardRef(() => Checkbox),
642
+ multi: true,
643
+ },
644
+ ], ngImport: i0, template: "<label class=\"gbt-checkbox\" [class.gbt-checkbox--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-checkbox{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-checkbox:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-checkbox--disabled{cursor:not-allowed;opacity:.5}.gbt-checkbox input{width:1rem;height:1rem;accent-color:var(--primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
645
+ }
646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Checkbox, decorators: [{
647
+ type: Component,
648
+ args: [{ selector: 'gbt-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
649
+ {
650
+ provide: NG_VALUE_ACCESSOR,
651
+ useExisting: forwardRef(() => Checkbox),
652
+ multi: true,
653
+ },
654
+ ], template: "<label class=\"gbt-checkbox\" [class.gbt-checkbox--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-checkbox{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-checkbox:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-checkbox--disabled{cursor:not-allowed;opacity:.5}.gbt-checkbox input{width:1rem;height:1rem;accent-color:var(--primary)}\n"] }]
655
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
543
656
 
544
657
  class Modal {
545
658
  isOpen = input.required(/* @ts-ignore */
@@ -604,11 +717,11 @@ class Modal {
604
717
  }
605
718
  }
606
719
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Modal, deps: [], target: i0.ɵɵFactoryTarget.Component });
607
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Modal, isStandalone: true, selector: "gbt-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-modal__backdrop\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"gbt-modal__dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n #dialog\n (keydown)=\"onDialogKeydown($event)\"\n >\n <header class=\"gbt-modal__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-modal__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-modal__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-modal__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-modal__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-modal__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-modal__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-modal__close\"\n (click)=\"closed.emit()\"\n [attr.aria-label]=\"closeLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </header>\n <div class=\"gbt-modal__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-modal__backdrop{position:fixed;inset:0;background:#0006;display:flex;align-items:center;justify-content:center;z-index:100}.gbt-modal__dialog{background:var(--bg-principal);border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);width:min(90vw,480px);max-height:90vh;overflow-y:auto}.gbt-modal__dialog:focus{outline:none}.gbt-modal__dialog:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-modal__header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-modal__header .gbt-modal__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-modal__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-modal__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-modal__body{padding:1.25rem;display:flex;flex-direction:column;gap:1rem}.gbt-modal__body>form{display:flex;flex-direction:column;gap:1rem}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
720
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Modal, isStandalone: true, selector: "gbt-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-modal__backdrop\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"gbt-modal__dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n #dialog\n (keydown)=\"onDialogKeydown($event)\"\n >\n <header class=\"gbt-modal__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-modal__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-modal__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-modal__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-modal__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-modal__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-modal__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-modal__close\"\n (click)=\"closed.emit()\"\n [attr.aria-label]=\"closeLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </header>\n <div class=\"gbt-modal__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-modal__backdrop{position:fixed;inset:0;background:#0006;display:flex;align-items:center;justify-content:center;z-index:1200}.gbt-modal__dialog{background:var(--bg-principal);border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);width:min(90vw,480px);max-height:90vh;overflow-y:auto}.gbt-modal__dialog:focus{outline:none}.gbt-modal__dialog:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-modal__header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-modal__header .gbt-modal__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-modal__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-modal__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-modal__body{padding:1.25rem;display:flex;flex-direction:column;gap:1rem}.gbt-modal__body>form{display:flex;flex-direction:column;gap:1rem}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
608
721
  }
609
722
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Modal, decorators: [{
610
723
  type: Component,
611
- args: [{ selector: 'gbt-modal', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-modal__backdrop\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"gbt-modal__dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n #dialog\n (keydown)=\"onDialogKeydown($event)\"\n >\n <header class=\"gbt-modal__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-modal__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-modal__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-modal__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-modal__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-modal__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-modal__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-modal__close\"\n (click)=\"closed.emit()\"\n [attr.aria-label]=\"closeLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </header>\n <div class=\"gbt-modal__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-modal__backdrop{position:fixed;inset:0;background:#0006;display:flex;align-items:center;justify-content:center;z-index:100}.gbt-modal__dialog{background:var(--bg-principal);border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);width:min(90vw,480px);max-height:90vh;overflow-y:auto}.gbt-modal__dialog:focus{outline:none}.gbt-modal__dialog:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-modal__header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-modal__header .gbt-modal__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-modal__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-modal__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-modal__body{padding:1.25rem;display:flex;flex-direction:column;gap:1rem}.gbt-modal__body>form{display:flex;flex-direction:column;gap:1rem}\n"] }]
724
+ args: [{ selector: 'gbt-modal', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isOpen()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"gbt-modal__backdrop\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"gbt-modal__dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n #dialog\n (keydown)=\"onDialogKeydown($event)\"\n >\n <header class=\"gbt-modal__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-modal__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-modal__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-modal__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-modal__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-modal__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-modal__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-modal__close\"\n (click)=\"closed.emit()\"\n [attr.aria-label]=\"closeLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </header>\n <div class=\"gbt-modal__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-modal__backdrop{position:fixed;inset:0;background:#0006;display:flex;align-items:center;justify-content:center;z-index:1200}.gbt-modal__dialog{background:var(--bg-principal);border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);width:min(90vw,480px);max-height:90vh;overflow-y:auto}.gbt-modal__dialog:focus{outline:none}.gbt-modal__dialog:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-modal__header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-modal__header .gbt-modal__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-modal__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-modal__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-modal__body{padding:1.25rem;display:flex;flex-direction:column;gap:1rem}.gbt-modal__body>form{display:flex;flex-direction:column;gap:1rem}\n"] }]
612
725
  }], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: true }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], dialog: [{ type: i0.ViewChild, args: ['dialog', { isSignal: true }] }], onEscape: [{
613
726
  type: HostListener,
614
727
  args: ['document:keydown.escape']
@@ -819,14 +932,14 @@ class SearchBar {
819
932
  this.searchQuery.set(this.keepQueryOnSelect() ? this.displayFn()(item) : '');
820
933
  }
821
934
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SearchBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
822
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: SearchBar, isStandalone: true, selector: "gbt-search-bar", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, results: { classPropertyName: "results", publicName: "results", isSignal: true, isRequired: false, transformFunction: null }, groupedResults: { classPropertyName: "groupedResults", publicName: "groupedResults", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, displayFn: { classPropertyName: "displayFn", publicName: "displayFn", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, keepQueryOnSelect: { classPropertyName: "keepQueryOnSelect", publicName: "keepQueryOnSelect", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, noResultsHint: { classPropertyName: "noResultsHint", publicName: "noResultsHint", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, resultsAnnouncement: { classPropertyName: "resultsAnnouncement", publicName: "resultsAnnouncement", isSignal: true, isRequired: false, transformFunction: null }, navigateHint: { classPropertyName: "navigateHint", publicName: "navigateHint", isSignal: true, isRequired: false, transformFunction: null }, selectHint: { classPropertyName: "selectHint", publicName: "selectHint", isSignal: true, isRequired: false, transformFunction: null }, closeHint: { classPropertyName: "closeHint", publicName: "closeHint", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { queryChange: "queryChange", itemSelected: "itemSelected", clear: "clear" }, host: { listeners: { "keydown": "onNavigationKeydown($event)", "document:click": "handleClickOutside($event)" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n<div class=\"gbt-sb-trigger\" [class.gbt-sb-trigger--open]=\"isFocused()\" (click)=\"focusSearch()\">\n <gbt-icon name=\"search\" class=\"gbt-sb-trigger__icon\" aria-hidden=\"true\" />\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"gbt-sb-trigger__input\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || placeholder()\"\n [value]=\"searchQuery()\"\n [attr.aria-expanded]=\"showOverlay()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"showOverlay() ? panelId() : null\"\n [attr.aria-activedescendant]=\"activeItemDomId()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (input)=\"onInput($event)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (searchQuery().length > 0) {\n <button\n type=\"button\"\n class=\"gbt-sb-trigger__clear\"\n (click)=\"onClear()\"\n [attr.aria-label]=\"clearLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</div>\n@if (showOverlay()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ resultsAnnouncement()(resultCount()) }}\n </div>\n}\n@if (showOverlay()) {\n <div class=\"gbt-sb-backdrop\" (click)=\"blurSearch()\" aria-hidden=\"true\"></div>\n <ng-template #footer>\n <div class=\"gbt-sb-footer\" aria-hidden=\"true\">\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2191</kbd>\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2193</kbd>\n {{ navigateHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u21B5</kbd>\n {{ selectHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">Esc</kbd>\n {{ closeHint() }}\n </span>\n </div>\n </ng-template>\n @if (hasNoResults()) {\n <div [id]=\"panelId()\" class=\"gbt-sb-panel\">\n <div class=\"gbt-sb-state\" role=\"status\">\n <gbt-icon name=\"search\" class=\"gbt-sb-state__icon\" aria-hidden=\"true\" />\n <span>{{ noResultsMessage() }}</span>\n <p class=\"gbt-sb-state__hint\">{{ noResultsHint() }}</p>\n </div>\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n [id]=\"panelId()\"\n class=\"gbt-sb-panel\"\n role=\"listbox\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGroupedResults()) {\n <div class=\"gbt-sb-list\">\n @for (category of indexedGroupedResults(); track category.label) {\n @if (category.items.length > 0) {\n <div class=\"gbt-sb-group-label\">\n @if (category.icon) {\n <gbt-icon [name]=\"category.icon\" aria-hidden=\"true\" />\n }\n {{ category.label }}\n <span class=\"gbt-sb-group-count\" aria-hidden=\"true\">{{\n category.items.length\n }}</span>\n </div>\n @for (entry of category.indexedItems; track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n @if (category.icon) {\n <gbt-icon\n [name]=\"category.icon\"\n class=\"gbt-sb-item__icon\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n }\n }\n </div>\n } @else if (results() && results()!.length > 0) {\n <div class=\"gbt-sb-list\">\n @for (entry of indexedResults(); track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n </div>\n }\n\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n }\n}\n", styles: [":host{position:relative;display:block}.gbt-sb-trigger{position:relative;z-index:1000;box-sizing:border-box;display:flex;align-items:center;gap:8px;height:40px;width:340px;padding:0 12px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:16px;transition:width .35s cubic-bezier(.34,1.56,.64,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);cursor:text}.gbt-sb-trigger--open{width:420px;border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-sb-trigger__icon{flex-shrink:0;color:var(--text-secondary);transition:color .2s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.34,1.56,.64,1)}.gbt-sb-trigger--open .gbt-sb-trigger__icon{color:var(--primary);transform:scale(1.1) rotate(5deg)}.gbt-sb-trigger__input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:14px;line-height:1.5}.gbt-sb-trigger__input::placeholder{color:var(--text-secondary)}.gbt-sb-trigger__input:focus-visible{outline:2px solid var(--primary);outline-offset:2px;border-radius:4px}.gbt-sb-trigger__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:6px;color:var(--text-secondary);cursor:pointer;transition:background .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-trigger__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-sb-trigger__clear:active{transform:scale(.9)}.gbt-sb-backdrop{position:fixed;inset:0;background:#0000004d;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:999;animation:gbt-search-bar-fade-in .2s cubic-bezier(.4,0,.2,1) both}.gbt-sb-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);width:420px;max-height:460px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius);box-shadow:0 16px 48px #0000002e,0 4px 12px #00000014;overflow:hidden;display:flex;flex-direction:column;z-index:1001;animation:gbt-search-bar-scale-in .25s cubic-bezier(.34,1.56,.64,1) both}.gbt-sb-list{flex:1;overflow-y:auto;padding:6px;display:flex;flex-direction:column}.gbt-sb-list::-webkit-scrollbar{width:6px}.gbt-sb-list::-webkit-scrollbar-track{background:transparent}.gbt-sb-list::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-sb-list::-webkit-scrollbar-thumb:hover{background:var(--border-color)}.gbt-sb-group-label{display:flex;align-items:center;gap:6px;padding:10px 10px 4px;color:var(--text-secondary);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.gbt-sb-group-count{margin-left:auto;padding:1px 7px;background:var(--bg-hover);border-radius:10px;font-size:11px;font-weight:600;color:var(--text-secondary)}.gbt-sb-item{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;background:transparent;border:none;border-radius:8px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-sb-item:hover{background:var(--bg-hover)}.gbt-sb-item--active{background:color-mix(in srgb,var(--primary) 9%,transparent)}.gbt-sb-item__icon{flex-shrink:0;color:var(--text-secondary);transition:color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-item--active .gbt-sb-item__icon{color:var(--primary)}.gbt-sb-item__label{flex:1;font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-sb-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;gap:12px;text-align:center}.gbt-sb-state span{color:var(--text-primary);font-size:14px;font-weight:500}.gbt-sb-state__icon{color:var(--text-secondary);opacity:.4}.gbt-sb-state__hint{margin:0;color:var(--text-secondary);font-size:12px}.gbt-sb-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 5px;background:var(--bg-hover);border:1px solid var(--border-color);border-bottom-width:2px;border-radius:5px;color:var(--text-secondary);font-size:11px;font-family:SF Mono,Monaco,Consolas,monospace;font-weight:500;line-height:1}.gbt-sb-kbd--sm{min-width:18px;height:18px;font-size:10px;border-radius:4px}.gbt-sb-footer{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:8px 12px;border-top:1px solid var(--border-color);background:var(--bg-hover)}.gbt-sb-footer__hint{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:11px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes gbt-search-bar-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-search-bar-scale-in{0%{opacity:0;transform:translate(-50%) scale(.96) translateY(-6px)}to{opacity:1;transform:translate(-50%) scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-sb-trigger{transition:border-color .15s,box-shadow .15s}.gbt-sb-trigger__icon{transition:color .15s;transform:none!important}.gbt-sb-trigger__clear{transition:none}.gbt-sb-trigger__clear:active{transform:none}.gbt-sb-backdrop,.gbt-sb-panel{animation:none}}@media screen and (max-width:800px){.gbt-sb-trigger,.gbt-sb-trigger--open{width:100%}.gbt-sb-panel{width:calc(100vw - 32px);max-height:360px}.gbt-sb-state{padding:32px 16px}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
935
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: SearchBar, isStandalone: true, selector: "gbt-search-bar", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, results: { classPropertyName: "results", publicName: "results", isSignal: true, isRequired: false, transformFunction: null }, groupedResults: { classPropertyName: "groupedResults", publicName: "groupedResults", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, displayFn: { classPropertyName: "displayFn", publicName: "displayFn", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, keepQueryOnSelect: { classPropertyName: "keepQueryOnSelect", publicName: "keepQueryOnSelect", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, noResultsHint: { classPropertyName: "noResultsHint", publicName: "noResultsHint", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, resultsAnnouncement: { classPropertyName: "resultsAnnouncement", publicName: "resultsAnnouncement", isSignal: true, isRequired: false, transformFunction: null }, navigateHint: { classPropertyName: "navigateHint", publicName: "navigateHint", isSignal: true, isRequired: false, transformFunction: null }, selectHint: { classPropertyName: "selectHint", publicName: "selectHint", isSignal: true, isRequired: false, transformFunction: null }, closeHint: { classPropertyName: "closeHint", publicName: "closeHint", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { queryChange: "queryChange", itemSelected: "itemSelected", clear: "clear" }, host: { listeners: { "keydown": "onNavigationKeydown($event)", "document:click": "handleClickOutside($event)" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n<div class=\"gbt-sb-trigger\" [class.gbt-sb-trigger--open]=\"isFocused()\" (click)=\"focusSearch()\">\n <gbt-icon name=\"search\" class=\"gbt-sb-trigger__icon\" aria-hidden=\"true\" />\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"gbt-sb-trigger__input\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || placeholder()\"\n [value]=\"searchQuery()\"\n [attr.aria-expanded]=\"showOverlay()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"showOverlay() ? panelId() : null\"\n [attr.aria-activedescendant]=\"activeItemDomId()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (input)=\"onInput($event)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (searchQuery().length > 0) {\n <button\n type=\"button\"\n class=\"gbt-sb-trigger__clear\"\n (click)=\"onClear()\"\n [attr.aria-label]=\"clearLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</div>\n@if (showOverlay()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ resultsAnnouncement()(resultCount()) }}\n </div>\n}\n@if (showOverlay()) {\n <div class=\"gbt-sb-backdrop\" (click)=\"blurSearch()\" aria-hidden=\"true\"></div>\n <ng-template #footer>\n <div class=\"gbt-sb-footer\" aria-hidden=\"true\">\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2191</kbd>\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2193</kbd>\n {{ navigateHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u21B5</kbd>\n {{ selectHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">Esc</kbd>\n {{ closeHint() }}\n </span>\n </div>\n </ng-template>\n @if (hasNoResults()) {\n <div [id]=\"panelId()\" class=\"gbt-sb-panel\">\n <div class=\"gbt-sb-state\" role=\"status\">\n <gbt-icon name=\"search\" class=\"gbt-sb-state__icon\" aria-hidden=\"true\" />\n <span>{{ noResultsMessage() }}</span>\n <p class=\"gbt-sb-state__hint\">{{ noResultsHint() }}</p>\n </div>\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n [id]=\"panelId()\"\n class=\"gbt-sb-panel\"\n role=\"listbox\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGroupedResults()) {\n <div class=\"gbt-sb-list\">\n @for (category of indexedGroupedResults(); track category.label) {\n @if (category.items.length > 0) {\n <div class=\"gbt-sb-group-label\">\n @if (category.icon) {\n <gbt-icon [name]=\"category.icon\" aria-hidden=\"true\" />\n }\n {{ category.label }}\n <span class=\"gbt-sb-group-count\" aria-hidden=\"true\">{{\n category.items.length\n }}</span>\n </div>\n @for (entry of category.indexedItems; track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n @if (category.icon) {\n <gbt-icon\n [name]=\"category.icon\"\n class=\"gbt-sb-item__icon\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n }\n }\n </div>\n } @else if (results() && results()!.length > 0) {\n <div class=\"gbt-sb-list\">\n @for (entry of indexedResults(); track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n </div>\n }\n\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n }\n}\n", styles: [":host{position:relative;display:block}.gbt-sb-trigger{position:relative;z-index:1000;box-sizing:border-box;display:flex;align-items:center;gap:8px;height:40px;width:340px;padding:0 12px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:16px;transition:width .35s cubic-bezier(.34,1.56,.64,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);cursor:text}.gbt-sb-trigger--open{width:420px;border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-sb-trigger__icon{flex-shrink:0;color:var(--text-secondary);transition:color .2s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.34,1.56,.64,1)}.gbt-sb-trigger--open .gbt-sb-trigger__icon{color:var(--primary);transform:scale(1.1) rotate(5deg)}.gbt-sb-trigger__input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:14px;line-height:1.5}.gbt-sb-trigger__input::placeholder{color:var(--text-secondary)}.gbt-sb-trigger__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:6px;color:var(--text-secondary);cursor:pointer;transition:background .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-trigger__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-sb-trigger__clear:active{transform:scale(.9)}.gbt-sb-backdrop{position:fixed;inset:0;background:#0000004d;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:999;animation:gbt-search-bar-fade-in .2s cubic-bezier(.4,0,.2,1) both}.gbt-sb-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);width:420px;max-height:460px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius);box-shadow:0 16px 48px #0000002e,0 4px 12px #00000014;overflow:hidden;display:flex;flex-direction:column;z-index:1001;animation:gbt-search-bar-scale-in .25s cubic-bezier(.34,1.56,.64,1) both}.gbt-sb-list{flex:1;overflow-y:auto;padding:6px;display:flex;flex-direction:column}.gbt-sb-list::-webkit-scrollbar{width:6px}.gbt-sb-list::-webkit-scrollbar-track{background:transparent}.gbt-sb-list::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-sb-list::-webkit-scrollbar-thumb:hover{background:var(--border-color)}.gbt-sb-group-label{display:flex;align-items:center;gap:6px;padding:10px 10px 4px;color:var(--text-secondary);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.gbt-sb-group-count{margin-left:auto;padding:1px 7px;background:var(--bg-hover);border-radius:10px;font-size:11px;font-weight:600;color:var(--text-secondary)}.gbt-sb-item{box-sizing:border-box;display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;background:transparent;border:none;border-radius:8px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-sb-item:hover{background:var(--bg-hover)}.gbt-sb-item--active{background:color-mix(in srgb,var(--primary) 9%,transparent)}.gbt-sb-item__icon{flex-shrink:0;color:var(--text-secondary);transition:color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-item--active .gbt-sb-item__icon{color:var(--primary)}.gbt-sb-item__label{flex:1;font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-sb-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;gap:12px;text-align:center}.gbt-sb-state span{color:var(--text-primary);font-size:14px;font-weight:500}.gbt-sb-state__icon{color:var(--text-secondary);opacity:.4}.gbt-sb-state__hint{margin:0;color:var(--text-secondary);font-size:12px}.gbt-sb-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 5px;background:var(--bg-hover);border:1px solid var(--border-color);border-bottom-width:2px;border-radius:5px;color:var(--text-secondary);font-size:11px;font-family:SF Mono,Monaco,Consolas,monospace;font-weight:500;line-height:1}.gbt-sb-kbd--sm{min-width:18px;height:18px;font-size:10px;border-radius:4px}.gbt-sb-footer{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:8px 12px;border-top:1px solid var(--border-color);background:var(--bg-hover)}.gbt-sb-footer__hint{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:11px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes gbt-search-bar-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-search-bar-scale-in{0%{opacity:0;transform:translate(-50%) scale(.96) translateY(-6px)}to{opacity:1;transform:translate(-50%) scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-sb-trigger{transition:border-color .15s,box-shadow .15s}.gbt-sb-trigger__icon{transition:color .15s;transform:none!important}.gbt-sb-trigger__clear{transition:none}.gbt-sb-trigger__clear:active{transform:none}.gbt-sb-backdrop,.gbt-sb-panel{animation:none}}@media screen and (max-width:800px){.gbt-sb-trigger,.gbt-sb-trigger--open{width:100%}.gbt-sb-panel{width:calc(100vw - 32px);max-height:360px}.gbt-sb-state{padding:32px 16px}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
823
936
  }
824
937
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SearchBar, decorators: [{
825
938
  type: Component,
826
939
  args: [{ selector: 'gbt-search-bar', standalone: true, imports: [Icon, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
827
940
  '(keydown)': 'onNavigationKeydown($event)',
828
941
  '(document:click)': 'handleClickOutside($event)',
829
- }, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n<div class=\"gbt-sb-trigger\" [class.gbt-sb-trigger--open]=\"isFocused()\" (click)=\"focusSearch()\">\n <gbt-icon name=\"search\" class=\"gbt-sb-trigger__icon\" aria-hidden=\"true\" />\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"gbt-sb-trigger__input\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || placeholder()\"\n [value]=\"searchQuery()\"\n [attr.aria-expanded]=\"showOverlay()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"showOverlay() ? panelId() : null\"\n [attr.aria-activedescendant]=\"activeItemDomId()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (input)=\"onInput($event)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (searchQuery().length > 0) {\n <button\n type=\"button\"\n class=\"gbt-sb-trigger__clear\"\n (click)=\"onClear()\"\n [attr.aria-label]=\"clearLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</div>\n@if (showOverlay()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ resultsAnnouncement()(resultCount()) }}\n </div>\n}\n@if (showOverlay()) {\n <div class=\"gbt-sb-backdrop\" (click)=\"blurSearch()\" aria-hidden=\"true\"></div>\n <ng-template #footer>\n <div class=\"gbt-sb-footer\" aria-hidden=\"true\">\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2191</kbd>\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2193</kbd>\n {{ navigateHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u21B5</kbd>\n {{ selectHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">Esc</kbd>\n {{ closeHint() }}\n </span>\n </div>\n </ng-template>\n @if (hasNoResults()) {\n <div [id]=\"panelId()\" class=\"gbt-sb-panel\">\n <div class=\"gbt-sb-state\" role=\"status\">\n <gbt-icon name=\"search\" class=\"gbt-sb-state__icon\" aria-hidden=\"true\" />\n <span>{{ noResultsMessage() }}</span>\n <p class=\"gbt-sb-state__hint\">{{ noResultsHint() }}</p>\n </div>\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n [id]=\"panelId()\"\n class=\"gbt-sb-panel\"\n role=\"listbox\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGroupedResults()) {\n <div class=\"gbt-sb-list\">\n @for (category of indexedGroupedResults(); track category.label) {\n @if (category.items.length > 0) {\n <div class=\"gbt-sb-group-label\">\n @if (category.icon) {\n <gbt-icon [name]=\"category.icon\" aria-hidden=\"true\" />\n }\n {{ category.label }}\n <span class=\"gbt-sb-group-count\" aria-hidden=\"true\">{{\n category.items.length\n }}</span>\n </div>\n @for (entry of category.indexedItems; track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n @if (category.icon) {\n <gbt-icon\n [name]=\"category.icon\"\n class=\"gbt-sb-item__icon\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n }\n }\n </div>\n } @else if (results() && results()!.length > 0) {\n <div class=\"gbt-sb-list\">\n @for (entry of indexedResults(); track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n </div>\n }\n\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n }\n}\n", styles: [":host{position:relative;display:block}.gbt-sb-trigger{position:relative;z-index:1000;box-sizing:border-box;display:flex;align-items:center;gap:8px;height:40px;width:340px;padding:0 12px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:16px;transition:width .35s cubic-bezier(.34,1.56,.64,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);cursor:text}.gbt-sb-trigger--open{width:420px;border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-sb-trigger__icon{flex-shrink:0;color:var(--text-secondary);transition:color .2s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.34,1.56,.64,1)}.gbt-sb-trigger--open .gbt-sb-trigger__icon{color:var(--primary);transform:scale(1.1) rotate(5deg)}.gbt-sb-trigger__input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:14px;line-height:1.5}.gbt-sb-trigger__input::placeholder{color:var(--text-secondary)}.gbt-sb-trigger__input:focus-visible{outline:2px solid var(--primary);outline-offset:2px;border-radius:4px}.gbt-sb-trigger__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:6px;color:var(--text-secondary);cursor:pointer;transition:background .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-trigger__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-sb-trigger__clear:active{transform:scale(.9)}.gbt-sb-backdrop{position:fixed;inset:0;background:#0000004d;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:999;animation:gbt-search-bar-fade-in .2s cubic-bezier(.4,0,.2,1) both}.gbt-sb-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);width:420px;max-height:460px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius);box-shadow:0 16px 48px #0000002e,0 4px 12px #00000014;overflow:hidden;display:flex;flex-direction:column;z-index:1001;animation:gbt-search-bar-scale-in .25s cubic-bezier(.34,1.56,.64,1) both}.gbt-sb-list{flex:1;overflow-y:auto;padding:6px;display:flex;flex-direction:column}.gbt-sb-list::-webkit-scrollbar{width:6px}.gbt-sb-list::-webkit-scrollbar-track{background:transparent}.gbt-sb-list::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-sb-list::-webkit-scrollbar-thumb:hover{background:var(--border-color)}.gbt-sb-group-label{display:flex;align-items:center;gap:6px;padding:10px 10px 4px;color:var(--text-secondary);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.gbt-sb-group-count{margin-left:auto;padding:1px 7px;background:var(--bg-hover);border-radius:10px;font-size:11px;font-weight:600;color:var(--text-secondary)}.gbt-sb-item{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;background:transparent;border:none;border-radius:8px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-sb-item:hover{background:var(--bg-hover)}.gbt-sb-item--active{background:color-mix(in srgb,var(--primary) 9%,transparent)}.gbt-sb-item__icon{flex-shrink:0;color:var(--text-secondary);transition:color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-item--active .gbt-sb-item__icon{color:var(--primary)}.gbt-sb-item__label{flex:1;font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-sb-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;gap:12px;text-align:center}.gbt-sb-state span{color:var(--text-primary);font-size:14px;font-weight:500}.gbt-sb-state__icon{color:var(--text-secondary);opacity:.4}.gbt-sb-state__hint{margin:0;color:var(--text-secondary);font-size:12px}.gbt-sb-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 5px;background:var(--bg-hover);border:1px solid var(--border-color);border-bottom-width:2px;border-radius:5px;color:var(--text-secondary);font-size:11px;font-family:SF Mono,Monaco,Consolas,monospace;font-weight:500;line-height:1}.gbt-sb-kbd--sm{min-width:18px;height:18px;font-size:10px;border-radius:4px}.gbt-sb-footer{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:8px 12px;border-top:1px solid var(--border-color);background:var(--bg-hover)}.gbt-sb-footer__hint{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:11px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes gbt-search-bar-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-search-bar-scale-in{0%{opacity:0;transform:translate(-50%) scale(.96) translateY(-6px)}to{opacity:1;transform:translate(-50%) scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-sb-trigger{transition:border-color .15s,box-shadow .15s}.gbt-sb-trigger__icon{transition:color .15s;transform:none!important}.gbt-sb-trigger__clear{transition:none}.gbt-sb-trigger__clear:active{transform:none}.gbt-sb-backdrop,.gbt-sb-panel{animation:none}}@media screen and (max-width:800px){.gbt-sb-trigger,.gbt-sb-trigger--open{width:100%}.gbt-sb-panel{width:calc(100vw - 32px);max-height:360px}.gbt-sb-state{padding:32px 16px}}\n"] }]
942
+ }, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n<div class=\"gbt-sb-trigger\" [class.gbt-sb-trigger--open]=\"isFocused()\" (click)=\"focusSearch()\">\n <gbt-icon name=\"search\" class=\"gbt-sb-trigger__icon\" aria-hidden=\"true\" />\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"gbt-sb-trigger__input\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || placeholder()\"\n [value]=\"searchQuery()\"\n [attr.aria-expanded]=\"showOverlay()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"showOverlay() ? panelId() : null\"\n [attr.aria-activedescendant]=\"activeItemDomId()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (input)=\"onInput($event)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (searchQuery().length > 0) {\n <button\n type=\"button\"\n class=\"gbt-sb-trigger__clear\"\n (click)=\"onClear()\"\n [attr.aria-label]=\"clearLabel()\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</div>\n@if (showOverlay()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ resultsAnnouncement()(resultCount()) }}\n </div>\n}\n@if (showOverlay()) {\n <div class=\"gbt-sb-backdrop\" (click)=\"blurSearch()\" aria-hidden=\"true\"></div>\n <ng-template #footer>\n <div class=\"gbt-sb-footer\" aria-hidden=\"true\">\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2191</kbd>\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u2193</kbd>\n {{ navigateHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">\u21B5</kbd>\n {{ selectHint() }}\n </span>\n <span class=\"gbt-sb-footer__hint\">\n <kbd class=\"gbt-sb-kbd gbt-sb-kbd--sm\">Esc</kbd>\n {{ closeHint() }}\n </span>\n </div>\n </ng-template>\n @if (hasNoResults()) {\n <div [id]=\"panelId()\" class=\"gbt-sb-panel\">\n <div class=\"gbt-sb-state\" role=\"status\">\n <gbt-icon name=\"search\" class=\"gbt-sb-state__icon\" aria-hidden=\"true\" />\n <span>{{ noResultsMessage() }}</span>\n <p class=\"gbt-sb-state__hint\">{{ noResultsHint() }}</p>\n </div>\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n [id]=\"panelId()\"\n class=\"gbt-sb-panel\"\n role=\"listbox\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGroupedResults()) {\n <div class=\"gbt-sb-list\">\n @for (category of indexedGroupedResults(); track category.label) {\n @if (category.items.length > 0) {\n <div class=\"gbt-sb-group-label\">\n @if (category.icon) {\n <gbt-icon [name]=\"category.icon\" aria-hidden=\"true\" />\n }\n {{ category.label }}\n <span class=\"gbt-sb-group-count\" aria-hidden=\"true\">{{\n category.items.length\n }}</span>\n </div>\n @for (entry of category.indexedItems; track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n @if (category.icon) {\n <gbt-icon\n [name]=\"category.icon\"\n class=\"gbt-sb-item__icon\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n }\n }\n </div>\n } @else if (results() && results()!.length > 0) {\n <div class=\"gbt-sb-list\">\n @for (entry of indexedResults(); track entry.index) {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n [id]=\"itemDomId(entry.index)\"\n class=\"gbt-sb-item\"\n [attr.aria-selected]=\"entry.index === activeIndex()\"\n [class.gbt-sb-item--active]=\"entry.index === activeIndex()\"\n (click)=\"onSelect(entry.item)\"\n (mouseenter)=\"activeIndex.set(entry.index)\"\n >\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item }\"\n ></ng-container>\n } @else {\n <span class=\"gbt-sb-item__label\">{{ entry.formatted }}</span>\n }\n </button>\n }\n </div>\n }\n\n <ng-container [ngTemplateOutlet]=\"footer\"></ng-container>\n </div>\n }\n}\n", styles: [":host{position:relative;display:block}.gbt-sb-trigger{position:relative;z-index:1000;box-sizing:border-box;display:flex;align-items:center;gap:8px;height:40px;width:340px;padding:0 12px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:16px;transition:width .35s cubic-bezier(.34,1.56,.64,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);cursor:text}.gbt-sb-trigger--open{width:420px;border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-sb-trigger__icon{flex-shrink:0;color:var(--text-secondary);transition:color .2s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.34,1.56,.64,1)}.gbt-sb-trigger--open .gbt-sb-trigger__icon{color:var(--primary);transform:scale(1.1) rotate(5deg)}.gbt-sb-trigger__input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:14px;line-height:1.5}.gbt-sb-trigger__input::placeholder{color:var(--text-secondary)}.gbt-sb-trigger__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:6px;color:var(--text-secondary);cursor:pointer;transition:background .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-trigger__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-sb-trigger__clear:active{transform:scale(.9)}.gbt-sb-backdrop{position:fixed;inset:0;background:#0000004d;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:999;animation:gbt-search-bar-fade-in .2s cubic-bezier(.4,0,.2,1) both}.gbt-sb-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);width:420px;max-height:460px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius);box-shadow:0 16px 48px #0000002e,0 4px 12px #00000014;overflow:hidden;display:flex;flex-direction:column;z-index:1001;animation:gbt-search-bar-scale-in .25s cubic-bezier(.34,1.56,.64,1) both}.gbt-sb-list{flex:1;overflow-y:auto;padding:6px;display:flex;flex-direction:column}.gbt-sb-list::-webkit-scrollbar{width:6px}.gbt-sb-list::-webkit-scrollbar-track{background:transparent}.gbt-sb-list::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-sb-list::-webkit-scrollbar-thumb:hover{background:var(--border-color)}.gbt-sb-group-label{display:flex;align-items:center;gap:6px;padding:10px 10px 4px;color:var(--text-secondary);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.gbt-sb-group-count{margin-left:auto;padding:1px 7px;background:var(--bg-hover);border-radius:10px;font-size:11px;font-weight:600;color:var(--text-secondary)}.gbt-sb-item{box-sizing:border-box;display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;background:transparent;border:none;border-radius:8px;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-sb-item:hover{background:var(--bg-hover)}.gbt-sb-item--active{background:color-mix(in srgb,var(--primary) 9%,transparent)}.gbt-sb-item__icon{flex-shrink:0;color:var(--text-secondary);transition:color .15s cubic-bezier(.4,0,.2,1)}.gbt-sb-item--active .gbt-sb-item__icon{color:var(--primary)}.gbt-sb-item__label{flex:1;font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-sb-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;gap:12px;text-align:center}.gbt-sb-state span{color:var(--text-primary);font-size:14px;font-weight:500}.gbt-sb-state__icon{color:var(--text-secondary);opacity:.4}.gbt-sb-state__hint{margin:0;color:var(--text-secondary);font-size:12px}.gbt-sb-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 5px;background:var(--bg-hover);border:1px solid var(--border-color);border-bottom-width:2px;border-radius:5px;color:var(--text-secondary);font-size:11px;font-family:SF Mono,Monaco,Consolas,monospace;font-weight:500;line-height:1}.gbt-sb-kbd--sm{min-width:18px;height:18px;font-size:10px;border-radius:4px}.gbt-sb-footer{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:8px 12px;border-top:1px solid var(--border-color);background:var(--bg-hover)}.gbt-sb-footer__hint{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:11px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes gbt-search-bar-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-search-bar-scale-in{0%{opacity:0;transform:translate(-50%) scale(.96) translateY(-6px)}to{opacity:1;transform:translate(-50%) scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-sb-trigger{transition:border-color .15s,box-shadow .15s}.gbt-sb-trigger__icon{transition:color .15s;transform:none!important}.gbt-sb-trigger__clear{transition:none}.gbt-sb-trigger__clear:active{transform:none}.gbt-sb-backdrop,.gbt-sb-panel{animation:none}}@media screen and (max-width:800px){.gbt-sb-trigger,.gbt-sb-trigger--open{width:100%}.gbt-sb-panel{width:calc(100vw - 32px);max-height:360px}.gbt-sb-state{padding:32px 16px}}\n"] }]
830
943
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], results: [{ type: i0.Input, args: [{ isSignal: true, alias: "results", required: false }] }], groupedResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupedResults", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], displayFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFn", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], keepQueryOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepQueryOnSelect", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], noResultsHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsHint", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], resultsAnnouncement: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultsAnnouncement", required: false }] }], navigateHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigateHint", required: false }] }], selectHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectHint", required: false }] }], closeHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeHint", required: false }] }], queryChange: [{ type: i0.Output, args: ["queryChange"] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], clear: [{ type: i0.Output, args: ["clear"] }], searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }] } });
831
944
 
832
945
  class Tab {
@@ -871,7 +984,7 @@ class Tabs {
871
984
  ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
872
985
  triggers = viewChildren('trigger', /* @ts-ignore */
873
986
  ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
874
- activeIndex = signal(0, /* @ts-ignore */
987
+ activeIndex = model(0, /* @ts-ignore */
875
988
  ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
876
989
  constructor() {
877
990
  effect(() => {
@@ -880,6 +993,21 @@ class Tabs {
880
993
  const groupId = this.id();
881
994
  tabs.forEach((tab, i) => tab.setState(i, i === active, groupId));
882
995
  });
996
+ // Self-heals an out-of-range `activeIndex` — e.g. a consumer binds it to
997
+ // a URL query parameter and the stored value no longer matches any tab —
998
+ // instead of leaving every panel hidden and every trigger out of the
999
+ // keyboard tab order with no way to reach the component at all.
1000
+ effect(() => {
1001
+ const count = this.tabs().length;
1002
+ if (count === 0) {
1003
+ return;
1004
+ }
1005
+ const current = this.activeIndex();
1006
+ const clamped = Math.min(Math.max(current, 0), count - 1);
1007
+ if (clamped !== current) {
1008
+ this.activeIndex.set(clamped);
1009
+ }
1010
+ });
883
1011
  }
884
1012
  select(index) {
885
1013
  this.activeIndex.set(index);
@@ -904,12 +1032,12 @@ class Tabs {
904
1032
  this.triggers()[next]?.nativeElement.focus();
905
1033
  }
906
1034
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Tabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
907
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Tabs, isStandalone: true, selector: "gbt-tabs", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "tabs", predicate: Tab, isSignal: true }], viewQueries: [{ propertyName: "triggers", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-tabs\">\n <div class=\"gbt-tabs__list\" role=\"tablist\">\n @for (tab of tabs(); track tab; let i = $index) {\n <button\n #trigger\n type=\"button\"\n class=\"gbt-tabs__trigger\"\n [class.gbt-tabs__trigger--active]=\"activeIndex() === i\"\n role=\"tab\"\n [id]=\"id() + '-trigger-' + i\"\n [attr.aria-selected]=\"activeIndex() === i\"\n [attr.aria-controls]=\"id() + '-panel-' + i\"\n [tabIndex]=\"activeIndex() === i ? 0 : -1\"\n (click)=\"select(i)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n {{ tab.label() }}\n </button>\n }\n </div>\n <div class=\"gbt-tabs__panels\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-tabs{display:flex;flex-direction:column}.gbt-tabs__list{display:flex;gap:.5rem;border-bottom:1px solid var(--border-color);overflow-x:auto}.gbt-tabs__trigger{appearance:none;background:none;border:none;border-bottom:2px solid transparent;padding:.75rem 1rem;font-size:.9375rem;font-weight:500;color:var(--text-secondary);cursor:pointer;white-space:nowrap;transition:color var(--site-transition-fast),border-color var(--site-transition-fast)}.gbt-tabs__trigger:hover{color:var(--text-primary)}.gbt-tabs__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:-2px;border-radius:var(--site-border-radius-sm)}.gbt-tabs__trigger--active{color:var(--primary);border-bottom-color:var(--primary)}.gbt-tabs__panels{padding-top:1rem;display:flex;flex-direction:column;gap:1rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1035
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Tabs, isStandalone: true, selector: "gbt-tabs", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, queries: [{ propertyName: "tabs", predicate: Tab, isSignal: true }], viewQueries: [{ propertyName: "triggers", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-tabs\">\n <div class=\"gbt-tabs__list\" role=\"tablist\">\n @for (tab of tabs(); track tab; let i = $index) {\n <button\n #trigger\n type=\"button\"\n class=\"gbt-tabs__trigger\"\n [class.gbt-tabs__trigger--active]=\"activeIndex() === i\"\n role=\"tab\"\n [id]=\"id() + '-trigger-' + i\"\n [attr.aria-selected]=\"activeIndex() === i\"\n [attr.aria-controls]=\"id() + '-panel-' + i\"\n [tabIndex]=\"activeIndex() === i ? 0 : -1\"\n (click)=\"select(i)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n {{ tab.label() }}\n </button>\n }\n </div>\n <div class=\"gbt-tabs__panels\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-tabs{display:flex;flex-direction:column}.gbt-tabs__list{display:flex;gap:.5rem;border-bottom:1px solid var(--border-color);overflow-x:auto}.gbt-tabs__trigger{appearance:none;background:none;border:none;border-bottom:2px solid transparent;padding:.75rem 1rem;font-size:.9375rem;font-weight:500;color:var(--text-secondary);cursor:pointer;white-space:nowrap;transition:color var(--site-transition-fast),border-color var(--site-transition-fast)}.gbt-tabs__trigger:hover{color:var(--text-primary)}.gbt-tabs__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:-2px;border-radius:var(--site-border-radius-sm)}.gbt-tabs__trigger--active{color:var(--primary);border-bottom-color:var(--primary)}.gbt-tabs__panels{padding-top:1rem;display:flex;flex-direction:column;gap:1rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
908
1036
  }
909
1037
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Tabs, decorators: [{
910
1038
  type: Component,
911
1039
  args: [{ selector: 'gbt-tabs', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-tabs\">\n <div class=\"gbt-tabs__list\" role=\"tablist\">\n @for (tab of tabs(); track tab; let i = $index) {\n <button\n #trigger\n type=\"button\"\n class=\"gbt-tabs__trigger\"\n [class.gbt-tabs__trigger--active]=\"activeIndex() === i\"\n role=\"tab\"\n [id]=\"id() + '-trigger-' + i\"\n [attr.aria-selected]=\"activeIndex() === i\"\n [attr.aria-controls]=\"id() + '-panel-' + i\"\n [tabIndex]=\"activeIndex() === i ? 0 : -1\"\n (click)=\"select(i)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n {{ tab.label() }}\n </button>\n }\n </div>\n <div class=\"gbt-tabs__panels\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block}.gbt-tabs{display:flex;flex-direction:column}.gbt-tabs__list{display:flex;gap:.5rem;border-bottom:1px solid var(--border-color);overflow-x:auto}.gbt-tabs__trigger{appearance:none;background:none;border:none;border-bottom:2px solid transparent;padding:.75rem 1rem;font-size:.9375rem;font-weight:500;color:var(--text-secondary);cursor:pointer;white-space:nowrap;transition:color var(--site-transition-fast),border-color var(--site-transition-fast)}.gbt-tabs__trigger:hover{color:var(--text-primary)}.gbt-tabs__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:-2px;border-radius:var(--site-border-radius-sm)}.gbt-tabs__trigger--active{color:var(--primary);border-bottom-color:var(--primary)}.gbt-tabs__panels{padding-top:1rem;display:flex;flex-direction:column;gap:1rem}\n"] }]
912
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => Tab), { isSignal: true }] }], triggers: [{ type: i0.ViewChildren, args: ['trigger', { isSignal: true }] }] } });
1040
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => Tab), { isSignal: true }] }], triggers: [{ type: i0.ViewChildren, args: ['trigger', { isSignal: true }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }] } });
913
1041
 
914
1042
  function linearScale(domain, range) {
915
1043
  const [d0, d1] = domain;
@@ -2290,6 +2418,9 @@ class Menu {
2290
2418
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2291
2419
  align = input('start', /* @ts-ignore */
2292
2420
  ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
2421
+ triggerIcon = input(null, /* @ts-ignore */
2422
+ ...(ngDevMode ? [{ debugName: "triggerIcon" }] : /* istanbul ignore next */ []));
2423
+ opened = output();
2293
2424
  open = signal(false, /* @ts-ignore */
2294
2425
  ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
2295
2426
  position = signal(null, /* @ts-ignore */
@@ -2303,6 +2434,7 @@ class Menu {
2303
2434
  if (this.open()) {
2304
2435
  this.updatePosition();
2305
2436
  this.focusAfterRender('first');
2437
+ this.opened.emit();
2306
2438
  }
2307
2439
  }
2308
2440
  close(returnFocus) {
@@ -2321,6 +2453,7 @@ class Menu {
2321
2453
  if (!this.open()) {
2322
2454
  this.open.set(true);
2323
2455
  this.updatePosition();
2456
+ this.opened.emit();
2324
2457
  }
2325
2458
  this.focusAfterRender(target);
2326
2459
  }
@@ -2393,7 +2526,7 @@ class Menu {
2393
2526
  }, { injector: this.injector });
2394
2527
  }
2395
2528
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Menu, deps: [], target: i0.ɵɵFactoryTarget.Component });
2396
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Menu, isStandalone: true, selector: "gbt-menu", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)", "focusout": "onFocusOut($event)", "window:scroll": "updatePosition()", "window:resize": "updatePosition()" } }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-menu\">\n <button\n #trigger\n type=\"button\"\n class=\"gbt-menu__trigger\"\n [class.gbt-menu__trigger--open]=\"open()\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"open()\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <span class=\"gbt-menu__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-menu__chevron\" aria-hidden=\"true\" />\n </button>\n\n @if (open() && position(); as pos) {\n <div\n #list\n class=\"gbt-menu__list\"\n role=\"menu\"\n tabindex=\"-1\"\n [attr.aria-label]=\"label()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n [style.right]=\"pos.right\"\n (keydown)=\"onListKeydown($event)\"\n (click)=\"onListClick()\"\n >\n <ng-content />\n </div>\n }\n</div>\n", styles: [":host{display:inline-block}.gbt-menu{position:relative;display:inline-block}.gbt-menu__trigger{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;border:1px solid transparent;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger:hover{background:var(--bg-hover)}.gbt-menu__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-menu__trigger--open{background:var(--bg-hover)}.gbt-menu__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger--open .gbt-menu__chevron{transform:rotate(180deg)}.gbt-menu__list{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:180px;padding:6px;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-menu-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-menu-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-menu__list{animation:none}.gbt-menu__chevron{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2529
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Menu, isStandalone: true, selector: "gbt-menu", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, triggerIcon: { classPropertyName: "triggerIcon", publicName: "triggerIcon", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened" }, host: { listeners: { "document:click": "onDocumentClick($event)", "focusout": "onFocusOut($event)", "window:scroll": "updatePosition()", "window:resize": "updatePosition()" } }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-menu\">\n <button\n #trigger\n type=\"button\"\n class=\"gbt-menu__trigger\"\n [class.gbt-menu__trigger--open]=\"open()\"\n [class.gbt-menu__trigger--icon-only]=\"triggerIcon()\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerIcon() ? label() : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" aria-hidden=\"true\" />\n } @else {\n <span class=\"gbt-menu__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-menu__chevron\" aria-hidden=\"true\" />\n }\n </button>\n\n @if (open() && position(); as pos) {\n <div\n #list\n class=\"gbt-menu__list\"\n role=\"menu\"\n tabindex=\"-1\"\n [attr.aria-label]=\"label()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n [style.right]=\"pos.right\"\n (keydown)=\"onListKeydown($event)\"\n (click)=\"onListClick()\"\n >\n <ng-content />\n </div>\n }\n</div>\n", styles: [":host{display:inline-block}.gbt-menu{position:relative;display:inline-block}.gbt-menu__trigger{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;border:1px solid transparent;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger:hover{background:var(--bg-hover)}.gbt-menu__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-menu__trigger--open{background:var(--bg-hover)}.gbt-menu__trigger--icon-only{padding:.5rem;gap:0}.gbt-menu__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger--open .gbt-menu__chevron{transform:rotate(180deg)}.gbt-menu__list{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:180px;padding:6px;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-menu-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-menu-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-menu__list{animation:none}.gbt-menu__chevron{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2397
2530
  }
2398
2531
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Menu, decorators: [{
2399
2532
  type: Component,
@@ -2402,8 +2535,179 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
2402
2535
  '(focusout)': 'onFocusOut($event)',
2403
2536
  '(window:scroll)': 'updatePosition()',
2404
2537
  '(window:resize)': 'updatePosition()',
2405
- }, template: "<div class=\"gbt-menu\">\n <button\n #trigger\n type=\"button\"\n class=\"gbt-menu__trigger\"\n [class.gbt-menu__trigger--open]=\"open()\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"open()\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <span class=\"gbt-menu__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-menu__chevron\" aria-hidden=\"true\" />\n </button>\n\n @if (open() && position(); as pos) {\n <div\n #list\n class=\"gbt-menu__list\"\n role=\"menu\"\n tabindex=\"-1\"\n [attr.aria-label]=\"label()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n [style.right]=\"pos.right\"\n (keydown)=\"onListKeydown($event)\"\n (click)=\"onListClick()\"\n >\n <ng-content />\n </div>\n }\n</div>\n", styles: [":host{display:inline-block}.gbt-menu{position:relative;display:inline-block}.gbt-menu__trigger{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;border:1px solid transparent;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger:hover{background:var(--bg-hover)}.gbt-menu__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-menu__trigger--open{background:var(--bg-hover)}.gbt-menu__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger--open .gbt-menu__chevron{transform:rotate(180deg)}.gbt-menu__list{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:180px;padding:6px;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-menu-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-menu-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-menu__list{animation:none}.gbt-menu__chevron{transition:none}}\n"] }]
2406
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }] } });
2538
+ }, template: "<div class=\"gbt-menu\">\n <button\n #trigger\n type=\"button\"\n class=\"gbt-menu__trigger\"\n [class.gbt-menu__trigger--open]=\"open()\"\n [class.gbt-menu__trigger--icon-only]=\"triggerIcon()\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerIcon() ? label() : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n @if (triggerIcon(); as icon) {\n <gbt-icon [name]=\"icon\" aria-hidden=\"true\" />\n } @else {\n <span class=\"gbt-menu__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-menu__chevron\" aria-hidden=\"true\" />\n }\n </button>\n\n @if (open() && position(); as pos) {\n <div\n #list\n class=\"gbt-menu__list\"\n role=\"menu\"\n tabindex=\"-1\"\n [attr.aria-label]=\"label()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n [style.right]=\"pos.right\"\n (keydown)=\"onListKeydown($event)\"\n (click)=\"onListClick()\"\n >\n <ng-content />\n </div>\n }\n</div>\n", styles: [":host{display:inline-block}.gbt-menu{position:relative;display:inline-block}.gbt-menu__trigger{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:transparent;border:1px solid transparent;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger:hover{background:var(--bg-hover)}.gbt-menu__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-menu__trigger--open{background:var(--bg-hover)}.gbt-menu__trigger--icon-only{padding:.5rem;gap:0}.gbt-menu__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-menu__trigger--open .gbt-menu__chevron{transform:rotate(180deg)}.gbt-menu__list{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:180px;padding:6px;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-menu-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-menu-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-menu__list{animation:none}.gbt-menu__chevron{transition:none}}\n"] }]
2539
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], triggerIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerIcon", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }] } });
2540
+
2541
+ const ELLIPSIS = '…';
2542
+ function range(start, end) {
2543
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
2544
+ }
2545
+ function paginationRange(page, pageCount, siblingCount) {
2546
+ const totalPageNumbers = siblingCount + 5;
2547
+ if (totalPageNumbers >= pageCount) {
2548
+ return range(1, pageCount);
2549
+ }
2550
+ const leftSiblingIndex = Math.max(page - siblingCount, 1);
2551
+ const rightSiblingIndex = Math.min(page + siblingCount, pageCount);
2552
+ const shouldShowLeftDots = leftSiblingIndex > 2;
2553
+ // -2, not -1: a lone skipped page right before the last one isn't worth an
2554
+ // ellipsis — showing that page costs no more room than the "…" would.
2555
+ const shouldShowRightDots = rightSiblingIndex < pageCount - 2;
2556
+ if (!shouldShowLeftDots && shouldShowRightDots) {
2557
+ const leftItemCount = 3 + siblingCount * 2;
2558
+ return [...range(1, leftItemCount), ELLIPSIS, pageCount];
2559
+ }
2560
+ if (shouldShowLeftDots && !shouldShowRightDots) {
2561
+ const rightItemCount = 3 + siblingCount * 2;
2562
+ return [1, ELLIPSIS, ...range(pageCount - rightItemCount + 1, pageCount)];
2563
+ }
2564
+ return [1, ELLIPSIS, ...range(leftSiblingIndex, rightSiblingIndex), ELLIPSIS, pageCount];
2565
+ }
2566
+ class Pagination {
2567
+ page = input(1, /* @ts-ignore */
2568
+ ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
2569
+ pageSize = input(10, /* @ts-ignore */
2570
+ ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
2571
+ totalItems = input.required(/* @ts-ignore */
2572
+ ...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
2573
+ siblingCount = input(1, /* @ts-ignore */
2574
+ ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
2575
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2576
+ ariaLabel = input('Pagination', /* @ts-ignore */
2577
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2578
+ previousLabel = input('Previous page', /* @ts-ignore */
2579
+ ...(ngDevMode ? [{ debugName: "previousLabel" }] : /* istanbul ignore next */ []));
2580
+ nextLabel = input('Next page', /* @ts-ignore */
2581
+ ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
2582
+ pageLabel = input((page) => `Page ${page}`, /* @ts-ignore */
2583
+ ...(ngDevMode ? [{ debugName: "pageLabel" }] : /* istanbul ignore next */ []));
2584
+ pageSizeOptions = input([], /* @ts-ignore */
2585
+ ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
2586
+ pageSizeLabel = input((size) => `${size} / page`, /* @ts-ignore */
2587
+ ...(ngDevMode ? [{ debugName: "pageSizeLabel" }] : /* istanbul ignore next */ []));
2588
+ pageSizeSelectLabel = input('Rows per page', /* @ts-ignore */
2589
+ ...(ngDevMode ? [{ debugName: "pageSizeSelectLabel" }] : /* istanbul ignore next */ []));
2590
+ showItemsSummary = input(false, { ...(ngDevMode ? { debugName: "showItemsSummary" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2591
+ itemsSummaryLabel = input((shown, total) => `${shown} of ${total} items`, /* @ts-ignore */
2592
+ ...(ngDevMode ? [{ debugName: "itemsSummaryLabel" }] : /* istanbul ignore next */ []));
2593
+ pageChange = output();
2594
+ pageSizeChange = output();
2595
+ ELLIPSIS = ELLIPSIS;
2596
+ pageCount = computed(() => Math.max(1, Math.ceil(this.totalItems() / this.pageSize())), /* @ts-ignore */
2597
+ ...(ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []));
2598
+ items = computed(() => paginationRange(this.page(), this.pageCount(), this.siblingCount()), /* @ts-ignore */
2599
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
2600
+ itemsShown = computed(() => {
2601
+ const start = (this.page() - 1) * this.pageSize();
2602
+ return Math.max(0, Math.min(this.pageSize(), this.totalItems() - start));
2603
+ }, /* @ts-ignore */
2604
+ ...(ngDevMode ? [{ debugName: "itemsShown" }] : /* istanbul ignore next */ []));
2605
+ itemsSummary = computed(() => this.itemsSummaryLabel()(this.itemsShown(), this.totalItems()), /* @ts-ignore */
2606
+ ...(ngDevMode ? [{ debugName: "itemsSummary" }] : /* istanbul ignore next */ []));
2607
+ pageSizeSelectOptions = computed(() => this.pageSizeOptions().map((size) => ({ value: size, label: this.pageSizeLabel()(size) })), /* @ts-ignore */
2608
+ ...(ngDevMode ? [{ debugName: "pageSizeSelectOptions" }] : /* istanbul ignore next */ []));
2609
+ pageSizeControl = new FormControl(this.pageSize(), {
2610
+ nonNullable: true,
2611
+ });
2612
+ constructor() {
2613
+ effect(() => {
2614
+ const size = this.pageSize();
2615
+ if (this.pageSizeControl.value !== size) {
2616
+ this.pageSizeControl.setValue(size, { emitEvent: false });
2617
+ }
2618
+ });
2619
+ this.pageSizeControl.valueChanges.pipe(takeUntilDestroyed()).subscribe((size) => {
2620
+ this.pageSizeChange.emit(size);
2621
+ this.pageChange.emit(1);
2622
+ });
2623
+ // Self-heals a stale `page` — e.g. a filter shrinks `totalItems` while
2624
+ // the app was sitting on a now out-of-range page — instead of leaving
2625
+ // the pager stuck with no page marked current and a live "previous"
2626
+ // button pointing at a page that no longer exists.
2627
+ effect(() => {
2628
+ const count = this.pageCount();
2629
+ const current = this.page();
2630
+ const clamped = Math.min(Math.max(current, 1), count);
2631
+ if (clamped !== current) {
2632
+ this.pageChange.emit(clamped);
2633
+ }
2634
+ });
2635
+ }
2636
+ goTo(page) {
2637
+ if (this.disabled())
2638
+ return;
2639
+ const clamped = Math.min(Math.max(page, 1), this.pageCount());
2640
+ if (clamped === this.page())
2641
+ return;
2642
+ this.pageChange.emit(clamped);
2643
+ }
2644
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Pagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
2645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Pagination, isStandalone: true, selector: "gbt-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: true, transformFunction: null }, siblingCount: { classPropertyName: "siblingCount", publicName: "siblingCount", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, pageLabel: { classPropertyName: "pageLabel", publicName: "pageLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSizeLabel: { classPropertyName: "pageSizeLabel", publicName: "pageSizeLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeSelectLabel: { classPropertyName: "pageSizeSelectLabel", publicName: "pageSizeSelectLabel", isSignal: true, isRequired: false, transformFunction: null }, showItemsSummary: { classPropertyName: "showItemsSummary", publicName: "showItemsSummary", isSignal: true, isRequired: false, transformFunction: null }, itemsSummaryLabel: { classPropertyName: "itemsSummaryLabel", publicName: "itemsSummaryLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"gbt-pagination\">\n <div class=\"gbt-pagination__side gbt-pagination__side--start\">\n @if (showItemsSummary()) {\n <span class=\"gbt-pagination__summary\">{{ itemsSummary() }}</span>\n }\n </div>\n\n <nav [attr.aria-label]=\"ariaLabel()\">\n <ul class=\"gbt-pagination__list\">\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__nav\"\n [disabled]=\"disabled() || page() <= 1\"\n [attr.aria-label]=\"previousLabel()\"\n (click)=\"goTo(page() - 1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n </li>\n @for (item of items(); track $index) {\n @if (item === ELLIPSIS) {\n <li class=\"gbt-pagination__ellipsis\" aria-hidden=\"true\">{{ ELLIPSIS }}</li>\n } @else {\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__page\"\n [class.gbt-pagination__page--current]=\"item === page()\"\n [attr.aria-current]=\"item === page() ? 'page' : null\"\n [attr.aria-label]=\"pageLabel()(item)\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(item)\"\n >\n {{ item }}\n </button>\n </li>\n }\n }\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__nav\"\n [disabled]=\"disabled() || page() >= pageCount()\"\n [attr.aria-label]=\"nextLabel()\"\n (click)=\"goTo(page() + 1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </li>\n </ul>\n </nav>\n\n <div class=\"gbt-pagination__side gbt-pagination__side--end\">\n @if (pageSizeOptions().length > 0) {\n <gbt-select\n class=\"gbt-pagination__page-size\"\n size=\"sm\"\n [label]=\"pageSizeSelectLabel()\"\n [options]=\"pageSizeSelectOptions()\"\n [disabled]=\"disabled()\"\n [formControl]=\"pageSizeControl\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.gbt-pagination{display:flex;align-items:center;flex-wrap:wrap;gap:1rem}.gbt-pagination__side{display:flex;align-items:center;flex:1;min-width:0}.gbt-pagination__side--start{justify-content:flex-start}.gbt-pagination__side--end{justify-content:flex-end}.gbt-pagination__summary{color:var(--text-secondary);font-size:.8125rem;white-space:nowrap}.gbt-pagination__page-size{min-width:0}.gbt-pagination__list{display:flex;align-items:center;gap:.25rem;margin:0;padding:0;list-style:none}.gbt-pagination__nav,.gbt-pagination__page{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;padding:0 .375rem;border:none;border-radius:var(--site-border-radius-sm);background:transparent;color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-pagination__nav:hover:not(:disabled),.gbt-pagination__page:hover:not(:disabled){background:var(--bg-hover)}.gbt-pagination__nav:focus-visible,.gbt-pagination__page:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-pagination__nav:disabled,.gbt-pagination__page:disabled{color:var(--text-discret);cursor:not-allowed}.gbt-pagination__page--current{background:var(--primary);color:var(--text-on-primary);font-weight:600}.gbt-pagination__page--current:hover{background:var(--primary)}.gbt-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--text-discret)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "component", type: Select, selector: "gbt-select", inputs: ["id", "label", "size", "options", "multiple", "placeholder", "disabled", "required", "errorMessage", "selectedCountLabel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2646
+ }
2647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Pagination, decorators: [{
2648
+ type: Component,
2649
+ args: [{ selector: 'gbt-pagination', standalone: true, imports: [Icon, Select, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-pagination\">\n <div class=\"gbt-pagination__side gbt-pagination__side--start\">\n @if (showItemsSummary()) {\n <span class=\"gbt-pagination__summary\">{{ itemsSummary() }}</span>\n }\n </div>\n\n <nav [attr.aria-label]=\"ariaLabel()\">\n <ul class=\"gbt-pagination__list\">\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__nav\"\n [disabled]=\"disabled() || page() <= 1\"\n [attr.aria-label]=\"previousLabel()\"\n (click)=\"goTo(page() - 1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n </li>\n @for (item of items(); track $index) {\n @if (item === ELLIPSIS) {\n <li class=\"gbt-pagination__ellipsis\" aria-hidden=\"true\">{{ ELLIPSIS }}</li>\n } @else {\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__page\"\n [class.gbt-pagination__page--current]=\"item === page()\"\n [attr.aria-current]=\"item === page() ? 'page' : null\"\n [attr.aria-label]=\"pageLabel()(item)\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(item)\"\n >\n {{ item }}\n </button>\n </li>\n }\n }\n <li>\n <button\n type=\"button\"\n class=\"gbt-pagination__nav\"\n [disabled]=\"disabled() || page() >= pageCount()\"\n [attr.aria-label]=\"nextLabel()\"\n (click)=\"goTo(page() + 1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </li>\n </ul>\n </nav>\n\n <div class=\"gbt-pagination__side gbt-pagination__side--end\">\n @if (pageSizeOptions().length > 0) {\n <gbt-select\n class=\"gbt-pagination__page-size\"\n size=\"sm\"\n [label]=\"pageSizeSelectLabel()\"\n [options]=\"pageSizeSelectOptions()\"\n [disabled]=\"disabled()\"\n [formControl]=\"pageSizeControl\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.gbt-pagination{display:flex;align-items:center;flex-wrap:wrap;gap:1rem}.gbt-pagination__side{display:flex;align-items:center;flex:1;min-width:0}.gbt-pagination__side--start{justify-content:flex-start}.gbt-pagination__side--end{justify-content:flex-end}.gbt-pagination__summary{color:var(--text-secondary);font-size:.8125rem;white-space:nowrap}.gbt-pagination__page-size{min-width:0}.gbt-pagination__list{display:flex;align-items:center;gap:.25rem;margin:0;padding:0;list-style:none}.gbt-pagination__nav,.gbt-pagination__page{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;padding:0 .375rem;border:none;border-radius:var(--site-border-radius-sm);background:transparent;color:var(--text-primary);font-size:.875rem;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-pagination__nav:hover:not(:disabled),.gbt-pagination__page:hover:not(:disabled){background:var(--bg-hover)}.gbt-pagination__nav:focus-visible,.gbt-pagination__page:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-pagination__nav:disabled,.gbt-pagination__page:disabled{color:var(--text-discret);cursor:not-allowed}.gbt-pagination__page--current{background:var(--primary);color:var(--text-on-primary);font-weight:600}.gbt-pagination__page--current:hover{background:var(--primary)}.gbt-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--text-discret)}\n"] }]
2650
+ }], ctorParameters: () => [], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], siblingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "siblingCount", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], pageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLabel", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], pageSizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeLabel", required: false }] }], pageSizeSelectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeSelectLabel", required: false }] }], showItemsSummary: [{ type: i0.Input, args: [{ isSignal: true, alias: "showItemsSummary", required: false }] }], itemsSummaryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsSummaryLabel", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }] } });
2651
+
2652
+ class Breadcrumb {
2653
+ ariaLabel = input.required(/* @ts-ignore */
2654
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2655
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Breadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
2656
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: Breadcrumb, isStandalone: true, selector: "gbt-breadcrumb", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"gbt-breadcrumb\">\n <ol class=\"gbt-breadcrumb__list\">\n <ng-content select=\"[breadcrumb-ancestor]\" />\n <li class=\"gbt-breadcrumb__current\" aria-current=\"page\"><ng-content /></li>\n </ol>\n</nav>\n", styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2657
+ }
2658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Breadcrumb, decorators: [{
2659
+ type: Component,
2660
+ args: [{ selector: 'gbt-breadcrumb', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"gbt-breadcrumb\">\n <ol class=\"gbt-breadcrumb__list\">\n <ng-content select=\"[breadcrumb-ancestor]\" />\n <li class=\"gbt-breadcrumb__current\" aria-current=\"page\"><ng-content /></li>\n </ol>\n</nav>\n", styles: [":host{display:block}\n"] }]
2661
+ }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }] } });
2662
+
2663
+ class ConfirmDangerModal {
2664
+ isOpen = input.required(/* @ts-ignore */
2665
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
2666
+ heading = input.required(/* @ts-ignore */
2667
+ ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
2668
+ message = input.required(/* @ts-ignore */
2669
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
2670
+ confirmText = input.required(/* @ts-ignore */
2671
+ ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
2672
+ confirmInputLabel = input('Type to confirm', /* @ts-ignore */
2673
+ ...(ngDevMode ? [{ debugName: "confirmInputLabel" }] : /* istanbul ignore next */ []));
2674
+ confirmLabel = input('Confirm', /* @ts-ignore */
2675
+ ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
2676
+ cancelLabel = input('Cancel', /* @ts-ignore */
2677
+ ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
2678
+ closeLabel = input('Close', /* @ts-ignore */
2679
+ ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
2680
+ confirmed = output();
2681
+ closed = output();
2682
+ typed = signal('', /* @ts-ignore */
2683
+ ...(ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []));
2684
+ canConfirm = computed(() => this.typed().length > 0 && this.typed() === this.confirmText(), /* @ts-ignore */
2685
+ ...(ngDevMode ? [{ debugName: "canConfirm" }] : /* istanbul ignore next */ []));
2686
+ constructor() {
2687
+ // Cleared whenever the modal transitions to closed (Cancel, Escape,
2688
+ // backdrop, or the consumer setting isOpen false after a successful
2689
+ // confirm) — a later reopen must never show the previous attempt's text.
2690
+ effect(() => {
2691
+ if (!this.isOpen()) {
2692
+ this.typed.set('');
2693
+ }
2694
+ });
2695
+ }
2696
+ confirm() {
2697
+ if (this.canConfirm()) {
2698
+ this.confirmed.emit();
2699
+ }
2700
+ }
2701
+ cancel() {
2702
+ this.closed.emit();
2703
+ }
2704
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ConfirmDangerModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
2705
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: ConfirmDangerModal, isStandalone: true, selector: "gbt-confirm-danger-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, confirmText: { classPropertyName: "confirmText", publicName: "confirmText", isSignal: true, isRequired: true, transformFunction: null }, confirmInputLabel: { classPropertyName: "confirmInputLabel", publicName: "confirmInputLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", closed: "closed" }, ngImport: i0, template: "<gbt-modal\n [isOpen]=\"isOpen()\"\n [heading]=\"heading()\"\n [closeLabel]=\"closeLabel()\"\n (closed)=\"cancel()\"\n>\n <p class=\"gbt-confirm-danger-modal__message\">{{ message() }}</p>\n <gbt-input\n [label]=\"confirmInputLabel()\"\n [ngModel]=\"typed()\"\n (ngModelChange)=\"typed.set($event)\"\n />\n <div class=\"gbt-confirm-danger-modal__actions\">\n <gbt-button variant=\"secondary\" [text]=\"cancelLabel()\" (clicked)=\"cancel()\" />\n <gbt-button\n variant=\"danger\"\n [text]=\"confirmLabel()\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"confirm()\"\n />\n </div>\n</gbt-modal>\n", styles: [".gbt-confirm-danger-modal__message{margin:0;color:var(--text-secondary)}.gbt-confirm-danger-modal__actions{display:flex;justify-content:flex-end;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Modal, selector: "gbt-modal", inputs: ["isOpen", "heading", "headingLevel", "closeLabel"], outputs: ["closed"] }, { kind: "component", type: GbtInput, selector: "gbt-input", inputs: ["id", "label", "type", "required", "disabled", "placeholder", "errorMessage", "autocomplete", "showPasswordLabel", "hidePasswordLabel"], outputs: ["committed"] }, { kind: "component", type: Button, selector: "gbt-button", inputs: ["variant", "size", "type", "text", "iconName", "ariaLabel", "loading", "loadingLabel", "disabled"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2706
+ }
2707
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ConfirmDangerModal, decorators: [{
2708
+ type: Component,
2709
+ args: [{ selector: 'gbt-confirm-danger-modal', standalone: true, imports: [FormsModule, Modal, GbtInput, Button], changeDetection: ChangeDetectionStrategy.OnPush, template: "<gbt-modal\n [isOpen]=\"isOpen()\"\n [heading]=\"heading()\"\n [closeLabel]=\"closeLabel()\"\n (closed)=\"cancel()\"\n>\n <p class=\"gbt-confirm-danger-modal__message\">{{ message() }}</p>\n <gbt-input\n [label]=\"confirmInputLabel()\"\n [ngModel]=\"typed()\"\n (ngModelChange)=\"typed.set($event)\"\n />\n <div class=\"gbt-confirm-danger-modal__actions\">\n <gbt-button variant=\"secondary\" [text]=\"cancelLabel()\" (clicked)=\"cancel()\" />\n <gbt-button\n variant=\"danger\"\n [text]=\"confirmLabel()\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"confirm()\"\n />\n </div>\n</gbt-modal>\n", styles: [".gbt-confirm-danger-modal__message{margin:0;color:var(--text-secondary)}.gbt-confirm-danger-modal__actions{display:flex;justify-content:flex-end;gap:.5rem}\n"] }]
2710
+ }], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: true }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], confirmText: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmText", required: true }] }], confirmInputLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmInputLabel", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2407
2711
 
2408
2712
  const DEFAULT_DURATION_MS = 5000;
2409
2713
  const ASSERTIVE_VARIANTS = new Set(['warning', 'error']);
@@ -2459,11 +2763,11 @@ class Toaster {
2459
2763
  return VARIANT_ICONS[variant];
2460
2764
  }
2461
2765
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Toaster, deps: [], target: i0.ɵɵFactoryTarget.Component });
2462
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Toaster, isStandalone: true, selector: "gbt-toaster", inputs: { toasts: { classPropertyName: "toasts", publicName: "toasts", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, ngImport: i0, template: "<div class=\"gbt-toaster\" [attr.data-position]=\"position()\">\n @for (toast of toasts(); track toast.id) {\n <div\n class=\"gbt-toaster__item\"\n [attr.data-variant]=\"toast.variant\"\n [attr.role]=\"roleFor(toast.variant)\"\n aria-atomic=\"true\"\n >\n <span class=\"gbt-toaster__icon\">\n <gbt-icon [name]=\"iconFor(toast.variant)\" aria-hidden=\"true\" />\n </span>\n <p class=\"gbt-toaster__message\">{{ toast.message }}</p>\n <button\n type=\"button\"\n class=\"gbt-toaster__close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"dismissed.emit(toast.id)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n</div>\n", styles: [".gbt-toaster{position:fixed;z-index:100;display:flex;flex-direction:column;gap:.5rem;max-width:min(90vw,360px);pointer-events:none}.gbt-toaster[data-position=top-right]{top:1rem;right:1rem;align-items:flex-end}.gbt-toaster[data-position=top-left]{top:1rem;left:1rem;align-items:flex-start}.gbt-toaster[data-position=top-center]{top:1rem;left:50%;align-items:center;transform:translate(-50%)}.gbt-toaster[data-position=bottom-right]{right:1rem;bottom:1rem;flex-direction:column-reverse;align-items:flex-end}.gbt-toaster[data-position=bottom-left]{bottom:1rem;left:1rem;flex-direction:column-reverse;align-items:flex-start}.gbt-toaster[data-position=bottom-center]{bottom:1rem;left:50%;flex-direction:column-reverse;align-items:center;transform:translate(-50%)}.gbt-toaster__item{display:flex;align-items:flex-start;gap:.625rem;width:100%;padding:.75rem 1rem;pointer-events:auto;background:var(--bg-inverse);border:none;border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);animation:gbt-toaster-in var(--site-transition-base)}.gbt-toaster__item[data-variant=success] .gbt-toaster__icon{background:var(--color-success-vivid-base)}.gbt-toaster__item[data-variant=warning] .gbt-toaster__icon{background:var(--color-warning-vivid-base)}.gbt-toaster__item[data-variant=error] .gbt-toaster__icon{background:var(--color-error-vivid-base)}.gbt-toaster__item[data-variant=info] .gbt-toaster__icon{background:var(--color-info-vivid-base)}.gbt-toaster__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.875rem;height:1.875rem;margin-top:.0625rem;color:var(--text-on-color);border-radius:50%}.gbt-toaster__icon gbt-icon{width:1.125em;height:1.125em}.gbt-toaster__message{flex:1 1 auto;margin:.3125rem 0;color:var(--text-on-color);font-size:.875rem;line-height:1.4}.gbt-toaster__close{position:relative;display:inline-flex;flex:none;align-self:flex-start;margin-top:.3125rem;background:none;border:none;border-radius:50%;color:var(--text-on-color);opacity:.7;cursor:pointer;transition:opacity var(--site-transition-fast)}.gbt-toaster__close:hover,.gbt-toaster__close:focus-visible{opacity:1}.gbt-toaster__close:focus-visible{outline:2px solid var(--text-on-color);outline-offset:2px}.gbt-toaster__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}@keyframes gbt-toaster-in{0%{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2766
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Toaster, isStandalone: true, selector: "gbt-toaster", inputs: { toasts: { classPropertyName: "toasts", publicName: "toasts", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, ngImport: i0, template: "<div class=\"gbt-toaster\" [attr.data-position]=\"position()\">\n @for (toast of toasts(); track toast.id) {\n <div\n class=\"gbt-toaster__item\"\n [attr.data-variant]=\"toast.variant\"\n [attr.role]=\"roleFor(toast.variant)\"\n aria-atomic=\"true\"\n >\n <span class=\"gbt-toaster__icon\">\n <gbt-icon [name]=\"iconFor(toast.variant)\" aria-hidden=\"true\" />\n </span>\n <p class=\"gbt-toaster__message\">{{ toast.message }}</p>\n <button\n type=\"button\"\n class=\"gbt-toaster__close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"dismissed.emit(toast.id)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n</div>\n", styles: [".gbt-toaster{position:fixed;z-index:1300;display:flex;flex-direction:column;gap:.5rem;max-width:min(90vw,360px);pointer-events:none}.gbt-toaster[data-position=top-right]{top:1rem;right:1rem;align-items:flex-end}.gbt-toaster[data-position=top-left]{top:1rem;left:1rem;align-items:flex-start}.gbt-toaster[data-position=top-center]{top:1rem;left:50%;align-items:center;transform:translate(-50%)}.gbt-toaster[data-position=bottom-right]{right:1rem;bottom:1rem;flex-direction:column-reverse;align-items:flex-end}.gbt-toaster[data-position=bottom-left]{bottom:1rem;left:1rem;flex-direction:column-reverse;align-items:flex-start}.gbt-toaster[data-position=bottom-center]{bottom:1rem;left:50%;flex-direction:column-reverse;align-items:center;transform:translate(-50%)}.gbt-toaster__item{box-sizing:border-box;display:flex;align-items:flex-start;gap:.625rem;width:100%;padding:.75rem 1rem;pointer-events:auto;background:var(--bg-inverse);border:none;border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);animation:gbt-toaster-in var(--site-transition-base)}.gbt-toaster__item[data-variant=success] .gbt-toaster__icon{background:var(--color-success-vivid-base)}.gbt-toaster__item[data-variant=warning] .gbt-toaster__icon{background:var(--color-warning-vivid-base)}.gbt-toaster__item[data-variant=error] .gbt-toaster__icon{background:var(--color-error-vivid-base)}.gbt-toaster__item[data-variant=info] .gbt-toaster__icon{background:var(--color-info-vivid-base)}.gbt-toaster__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.875rem;height:1.875rem;margin-top:.0625rem;color:var(--text-on-color);border-radius:50%}.gbt-toaster__icon gbt-icon{width:1.125em;height:1.125em}.gbt-toaster__message{flex:1 1 auto;margin:.3125rem 0;color:var(--text-on-color);font-size:.875rem;line-height:1.4}.gbt-toaster__close{position:relative;display:inline-flex;flex:none;align-self:flex-start;margin-top:.3125rem;background:none;border:none;border-radius:50%;color:var(--text-on-color);opacity:.7;cursor:pointer;transition:opacity var(--site-transition-fast)}.gbt-toaster__close:hover,.gbt-toaster__close:focus-visible{opacity:1}.gbt-toaster__close:focus-visible{outline:2px solid var(--text-on-color);outline-offset:2px}.gbt-toaster__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}@keyframes gbt-toaster-in{0%{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2463
2767
  }
2464
2768
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Toaster, decorators: [{
2465
2769
  type: Component,
2466
- args: [{ selector: 'gbt-toaster', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-toaster\" [attr.data-position]=\"position()\">\n @for (toast of toasts(); track toast.id) {\n <div\n class=\"gbt-toaster__item\"\n [attr.data-variant]=\"toast.variant\"\n [attr.role]=\"roleFor(toast.variant)\"\n aria-atomic=\"true\"\n >\n <span class=\"gbt-toaster__icon\">\n <gbt-icon [name]=\"iconFor(toast.variant)\" aria-hidden=\"true\" />\n </span>\n <p class=\"gbt-toaster__message\">{{ toast.message }}</p>\n <button\n type=\"button\"\n class=\"gbt-toaster__close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"dismissed.emit(toast.id)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n</div>\n", styles: [".gbt-toaster{position:fixed;z-index:100;display:flex;flex-direction:column;gap:.5rem;max-width:min(90vw,360px);pointer-events:none}.gbt-toaster[data-position=top-right]{top:1rem;right:1rem;align-items:flex-end}.gbt-toaster[data-position=top-left]{top:1rem;left:1rem;align-items:flex-start}.gbt-toaster[data-position=top-center]{top:1rem;left:50%;align-items:center;transform:translate(-50%)}.gbt-toaster[data-position=bottom-right]{right:1rem;bottom:1rem;flex-direction:column-reverse;align-items:flex-end}.gbt-toaster[data-position=bottom-left]{bottom:1rem;left:1rem;flex-direction:column-reverse;align-items:flex-start}.gbt-toaster[data-position=bottom-center]{bottom:1rem;left:50%;flex-direction:column-reverse;align-items:center;transform:translate(-50%)}.gbt-toaster__item{display:flex;align-items:flex-start;gap:.625rem;width:100%;padding:.75rem 1rem;pointer-events:auto;background:var(--bg-inverse);border:none;border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);animation:gbt-toaster-in var(--site-transition-base)}.gbt-toaster__item[data-variant=success] .gbt-toaster__icon{background:var(--color-success-vivid-base)}.gbt-toaster__item[data-variant=warning] .gbt-toaster__icon{background:var(--color-warning-vivid-base)}.gbt-toaster__item[data-variant=error] .gbt-toaster__icon{background:var(--color-error-vivid-base)}.gbt-toaster__item[data-variant=info] .gbt-toaster__icon{background:var(--color-info-vivid-base)}.gbt-toaster__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.875rem;height:1.875rem;margin-top:.0625rem;color:var(--text-on-color);border-radius:50%}.gbt-toaster__icon gbt-icon{width:1.125em;height:1.125em}.gbt-toaster__message{flex:1 1 auto;margin:.3125rem 0;color:var(--text-on-color);font-size:.875rem;line-height:1.4}.gbt-toaster__close{position:relative;display:inline-flex;flex:none;align-self:flex-start;margin-top:.3125rem;background:none;border:none;border-radius:50%;color:var(--text-on-color);opacity:.7;cursor:pointer;transition:opacity var(--site-transition-fast)}.gbt-toaster__close:hover,.gbt-toaster__close:focus-visible{opacity:1}.gbt-toaster__close:focus-visible{outline:2px solid var(--text-on-color);outline-offset:2px}.gbt-toaster__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}@keyframes gbt-toaster-in{0%{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
2770
+ args: [{ selector: 'gbt-toaster', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-toaster\" [attr.data-position]=\"position()\">\n @for (toast of toasts(); track toast.id) {\n <div\n class=\"gbt-toaster__item\"\n [attr.data-variant]=\"toast.variant\"\n [attr.role]=\"roleFor(toast.variant)\"\n aria-atomic=\"true\"\n >\n <span class=\"gbt-toaster__icon\">\n <gbt-icon [name]=\"iconFor(toast.variant)\" aria-hidden=\"true\" />\n </span>\n <p class=\"gbt-toaster__message\">{{ toast.message }}</p>\n <button\n type=\"button\"\n class=\"gbt-toaster__close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"dismissed.emit(toast.id)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n</div>\n", styles: [".gbt-toaster{position:fixed;z-index:1300;display:flex;flex-direction:column;gap:.5rem;max-width:min(90vw,360px);pointer-events:none}.gbt-toaster[data-position=top-right]{top:1rem;right:1rem;align-items:flex-end}.gbt-toaster[data-position=top-left]{top:1rem;left:1rem;align-items:flex-start}.gbt-toaster[data-position=top-center]{top:1rem;left:50%;align-items:center;transform:translate(-50%)}.gbt-toaster[data-position=bottom-right]{right:1rem;bottom:1rem;flex-direction:column-reverse;align-items:flex-end}.gbt-toaster[data-position=bottom-left]{bottom:1rem;left:1rem;flex-direction:column-reverse;align-items:flex-start}.gbt-toaster[data-position=bottom-center]{bottom:1rem;left:50%;flex-direction:column-reverse;align-items:center;transform:translate(-50%)}.gbt-toaster__item{box-sizing:border-box;display:flex;align-items:flex-start;gap:.625rem;width:100%;padding:.75rem 1rem;pointer-events:auto;background:var(--bg-inverse);border:none;border-radius:var(--site-border-radius);box-shadow:var(--site-shadow-lg);animation:gbt-toaster-in var(--site-transition-base)}.gbt-toaster__item[data-variant=success] .gbt-toaster__icon{background:var(--color-success-vivid-base)}.gbt-toaster__item[data-variant=warning] .gbt-toaster__icon{background:var(--color-warning-vivid-base)}.gbt-toaster__item[data-variant=error] .gbt-toaster__icon{background:var(--color-error-vivid-base)}.gbt-toaster__item[data-variant=info] .gbt-toaster__icon{background:var(--color-info-vivid-base)}.gbt-toaster__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.875rem;height:1.875rem;margin-top:.0625rem;color:var(--text-on-color);border-radius:50%}.gbt-toaster__icon gbt-icon{width:1.125em;height:1.125em}.gbt-toaster__message{flex:1 1 auto;margin:.3125rem 0;color:var(--text-on-color);font-size:.875rem;line-height:1.4}.gbt-toaster__close{position:relative;display:inline-flex;flex:none;align-self:flex-start;margin-top:.3125rem;background:none;border:none;border-radius:50%;color:var(--text-on-color);opacity:.7;cursor:pointer;transition:opacity var(--site-transition-fast)}.gbt-toaster__close:hover,.gbt-toaster__close:focus-visible{opacity:1}.gbt-toaster__close:focus-visible{outline:2px solid var(--text-on-color);outline-offset:2px}.gbt-toaster__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}@keyframes gbt-toaster-in{0%{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
2467
2771
  }], ctorParameters: () => [], propDecorators: { toasts: [{ type: i0.Input, args: [{ isSignal: true, alias: "toasts", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
2468
2772
 
2469
2773
  const SHOW_DELAY_MS = 400;
@@ -2740,9 +3044,238 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
2740
3044
  ], template: "<div class=\"gbt-textarea\">\n @if (label()) {\n <label [for]=\"id()\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <textarea\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [disabled]=\"isDisabled()\"\n [rows]=\"rows()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n >{{ value() }}</textarea\n >\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-textarea__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [":host{display:block}.gbt-textarea{display:flex;flex-direction:column;gap:.375rem}.gbt-textarea label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-textarea textarea{box-sizing:border-box;width:100%;padding:.5rem .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);resize:vertical;transition:border-color var(--site-transition-fast)}.gbt-textarea textarea:focus{outline:none;border-color:var(--primary)}.gbt-textarea textarea:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-textarea textarea:disabled{background:var(--bg-panel);cursor:not-allowed;resize:none}.gbt-textarea__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
2741
3045
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], committed: [{ type: i0.Output, args: ["committed"] }] } });
2742
3046
 
3047
+ let nextAutocompleteId = 0;
3048
+ class Autocomplete {
3049
+ elementRef = inject(ElementRef);
3050
+ id = input(`gbt-autocomplete-${++nextAutocompleteId}`, /* @ts-ignore */
3051
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3052
+ label = input('', /* @ts-ignore */
3053
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3054
+ placeholder = input('', /* @ts-ignore */
3055
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3056
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3057
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3058
+ errorMessage = input(null, /* @ts-ignore */
3059
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3060
+ search = input.required(/* @ts-ignore */
3061
+ ...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
3062
+ displayFn = input((item) => String(item), /* @ts-ignore */
3063
+ ...(ngDevMode ? [{ debugName: "displayFn" }] : /* istanbul ignore next */ []));
3064
+ itemTemplate = input(/* @ts-ignore */
3065
+ ...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
3066
+ debounceMs = input(300, /* @ts-ignore */
3067
+ ...(ngDevMode ? [{ debugName: "debounceMs" }] : /* istanbul ignore next */ []));
3068
+ minLength = input(1, /* @ts-ignore */
3069
+ ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
3070
+ loadingMessage = input('Searching…', /* @ts-ignore */
3071
+ ...(ngDevMode ? [{ debugName: "loadingMessage" }] : /* istanbul ignore next */ []));
3072
+ noResultsMessage = input('No results', /* @ts-ignore */
3073
+ ...(ngDevMode ? [{ debugName: "noResultsMessage" }] : /* istanbul ignore next */ []));
3074
+ searchErrorMessage = input('Search failed', /* @ts-ignore */
3075
+ ...(ngDevMode ? [{ debugName: "searchErrorMessage" }] : /* istanbul ignore next */ []));
3076
+ resultsAnnouncement = input((count) => `${count} result${count !== 1 ? 's' : ''}`, /* @ts-ignore */
3077
+ ...(ngDevMode ? [{ debugName: "resultsAnnouncement" }] : /* istanbul ignore next */ []));
3078
+ itemSelected = output();
3079
+ query = signal('', /* @ts-ignore */
3080
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
3081
+ open = signal(false, /* @ts-ignore */
3082
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
3083
+ results = signal([], /* @ts-ignore */
3084
+ ...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
3085
+ loading = signal(false, /* @ts-ignore */
3086
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
3087
+ searchFailed = signal(false, /* @ts-ignore */
3088
+ ...(ngDevMode ? [{ debugName: "searchFailed" }] : /* istanbul ignore next */ []));
3089
+ activeIndex = signal(0, /* @ts-ignore */
3090
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
3091
+ selectedItem = signal(null, /* @ts-ignore */
3092
+ ...(ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []));
3093
+ panelStyle = signal(null, /* @ts-ignore */
3094
+ ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
3095
+ formDisabled = signal(false, /* @ts-ignore */
3096
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3097
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3098
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
3099
+ hasNoResults = computed(() => this.open() && !this.loading() && !this.searchFailed() && this.results().length === 0, /* @ts-ignore */
3100
+ ...(ngDevMode ? [{ debugName: "hasNoResults" }] : /* istanbul ignore next */ []));
3101
+ activeOptionId = computed(() => this.open() && this.results().length > 0 ? `${this.id()}-option-${this.activeIndex()}` : null, /* @ts-ignore */
3102
+ ...(ngDevMode ? [{ debugName: "activeOptionId" }] : /* istanbul ignore next */ []));
3103
+ onChange = () => { };
3104
+ onTouched = () => { };
3105
+ requestSeq = 0;
3106
+ debounceHandle;
3107
+ subscription;
3108
+ setDisabledState(isDisabled) {
3109
+ this.formDisabled.set(isDisabled);
3110
+ }
3111
+ writeValue(value) {
3112
+ this.selectedItem.set(value);
3113
+ this.query.set(value === null || value === undefined ? '' : this.displayFn()(value));
3114
+ }
3115
+ registerOnChange(fn) {
3116
+ this.onChange = fn;
3117
+ }
3118
+ registerOnTouched(fn) {
3119
+ this.onTouched = fn;
3120
+ }
3121
+ onInput(event) {
3122
+ const value = event.target.value;
3123
+ this.query.set(value);
3124
+ this.activeIndex.set(0);
3125
+ if (this.selectedItem() !== null) {
3126
+ this.selectedItem.set(null);
3127
+ this.onChange(null);
3128
+ }
3129
+ this.scheduleSearch(value);
3130
+ }
3131
+ onFocus() {
3132
+ if (this.query().trim().length >= this.minLength() &&
3133
+ (this.results().length > 0 || this.searchFailed())) {
3134
+ this.open.set(true);
3135
+ this.updatePanelPosition();
3136
+ }
3137
+ }
3138
+ onBlur() {
3139
+ this.onTouched();
3140
+ setTimeout(() => {
3141
+ if (!this.elementRef.nativeElement.contains(document.activeElement)) {
3142
+ this.open.set(false);
3143
+ }
3144
+ }, 200);
3145
+ }
3146
+ scheduleSearch(value) {
3147
+ clearTimeout(this.debounceHandle);
3148
+ if (value.trim().length < this.minLength()) {
3149
+ this.requestSeq++;
3150
+ this.subscription?.unsubscribe();
3151
+ this.open.set(false);
3152
+ this.results.set([]);
3153
+ this.loading.set(false);
3154
+ this.searchFailed.set(false);
3155
+ return;
3156
+ }
3157
+ this.debounceHandle = setTimeout(() => this.runSearch(value), this.debounceMs());
3158
+ }
3159
+ runSearch(query) {
3160
+ const seq = ++this.requestSeq;
3161
+ this.subscription?.unsubscribe();
3162
+ this.loading.set(true);
3163
+ this.searchFailed.set(false);
3164
+ this.open.set(true);
3165
+ this.updatePanelPosition();
3166
+ const applyResults = (items) => {
3167
+ if (seq !== this.requestSeq)
3168
+ return;
3169
+ this.results.set(items);
3170
+ this.loading.set(false);
3171
+ this.activeIndex.set(0);
3172
+ this.updatePanelPosition();
3173
+ };
3174
+ const applyError = () => {
3175
+ if (seq !== this.requestSeq)
3176
+ return;
3177
+ this.results.set([]);
3178
+ this.loading.set(false);
3179
+ this.searchFailed.set(true);
3180
+ this.updatePanelPosition();
3181
+ };
3182
+ const result = this.search()(query);
3183
+ if (isObservable(result)) {
3184
+ this.subscription = result.subscribe({ next: applyResults, error: applyError });
3185
+ }
3186
+ else {
3187
+ result.then(applyResults, applyError);
3188
+ }
3189
+ }
3190
+ updatePanelPosition() {
3191
+ if (!this.open()) {
3192
+ return;
3193
+ }
3194
+ const trigger = this.elementRef.nativeElement.querySelector('.gbt-autocomplete__input');
3195
+ if (!trigger) {
3196
+ return;
3197
+ }
3198
+ const rect = trigger.getBoundingClientRect();
3199
+ this.panelStyle.set({
3200
+ top: `${rect.bottom + 6}px`,
3201
+ left: `${rect.left}px`,
3202
+ width: `${rect.width}px`,
3203
+ });
3204
+ }
3205
+ selectOption(item) {
3206
+ this.selectedItem.set(item);
3207
+ this.query.set(this.displayFn()(item));
3208
+ this.results.set([]);
3209
+ this.open.set(false);
3210
+ this.onChange(item);
3211
+ this.onTouched();
3212
+ this.itemSelected.emit(item);
3213
+ }
3214
+ onKeydown(event) {
3215
+ if (this.isDisabled()) {
3216
+ return;
3217
+ }
3218
+ if (event.key === 'Escape') {
3219
+ if (this.open()) {
3220
+ event.preventDefault();
3221
+ event.stopPropagation();
3222
+ this.open.set(false);
3223
+ }
3224
+ return;
3225
+ }
3226
+ if (!this.open() || this.results().length === 0) {
3227
+ return;
3228
+ }
3229
+ const results = this.results();
3230
+ switch (event.key) {
3231
+ case 'ArrowDown':
3232
+ event.preventDefault();
3233
+ this.activeIndex.update((i) => Math.min(i + 1, results.length - 1));
3234
+ break;
3235
+ case 'ArrowUp':
3236
+ event.preventDefault();
3237
+ this.activeIndex.update((i) => Math.max(i - 1, 0));
3238
+ break;
3239
+ case 'Enter': {
3240
+ event.preventDefault();
3241
+ const active = results[this.activeIndex()];
3242
+ if (active) {
3243
+ this.selectOption(active);
3244
+ }
3245
+ break;
3246
+ }
3247
+ }
3248
+ }
3249
+ ngOnDestroy() {
3250
+ clearTimeout(this.debounceHandle);
3251
+ this.subscription?.unsubscribe();
3252
+ }
3253
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Autocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
3254
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: Autocomplete, isStandalone: true, selector: "gbt-autocomplete", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: true, transformFunction: null }, displayFn: { classPropertyName: "displayFn", publicName: "displayFn", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, loadingMessage: { classPropertyName: "loadingMessage", publicName: "loadingMessage", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, searchErrorMessage: { classPropertyName: "searchErrorMessage", publicName: "searchErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, resultsAnnouncement: { classPropertyName: "resultsAnnouncement", publicName: "resultsAnnouncement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, host: { listeners: { "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" } }, providers: [
3255
+ {
3256
+ provide: NG_VALUE_ACCESSOR,
3257
+ useExisting: forwardRef(() => Autocomplete),
3258
+ multi: true,
3259
+ },
3260
+ ], ngImport: i0, 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 [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\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", 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%;padding:.5rem .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(--primary);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:8px;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"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3261
+ }
3262
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: Autocomplete, decorators: [{
3263
+ type: Component,
3264
+ args: [{ selector: 'gbt-autocomplete', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3265
+ '(window:scroll)': 'updatePanelPosition()',
3266
+ '(window:resize)': 'updatePanelPosition()',
3267
+ }, providers: [
3268
+ {
3269
+ provide: NG_VALUE_ACCESSOR,
3270
+ useExisting: forwardRef(() => Autocomplete),
3271
+ multi: true,
3272
+ },
3273
+ ], 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 [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\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", 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%;padding:.5rem .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(--primary);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:8px;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"] }]
3274
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: true }] }], displayFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFn", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], loadingMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMessage", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], searchErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchErrorMessage", required: false }] }], resultsAnnouncement: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultsAnnouncement", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }] } });
3275
+
2743
3276
  /**
2744
3277
  * Generated bundle index. Do not edit.
2745
3278
  */
2746
3279
 
2747
- export { AppShell, BarChart, BarSeries, Button, CHART_CONTEXT, Card, ChartAxis, ChartEmpty, ChartFrame, ChartLegend, ChartTable, ChartTooltip, Checkbox, DimensionCard, FunnelChart, GABARIT_VERSION, GaugeBar, GbtInput, Icon, IconRegistry, LineChart, LineSeries, Menu, Modal, RadioGroup, SearchBar, Select, Sparkline, Switch, Tab, Table, Tabs, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
3280
+ export { AppShell, Autocomplete, Badge, BarChart, BarSeries, Breadcrumb, Button, CHART_CONTEXT, Card, ChartAxis, ChartEmpty, ChartFrame, ChartLegend, ChartTable, ChartTooltip, Checkbox, ConfirmDangerModal, DimensionCard, EmptyState, FunnelChart, GABARIT_VERSION, GaugeBar, GbtInput, Icon, IconRegistry, LineChart, LineSeries, ListToolbar, Menu, Modal, Pagination, RadioGroup, SearchBar, Select, Sparkline, Switch, Tab, Table, Tabs, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
2748
3281
  //# sourceMappingURL=masmarino-gabarit.mjs.map