@masmarino/gabarit 0.7.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 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';
2
+ import { Injectable, inject, input, computed, ChangeDetectionStrategy, Component, output, signal, viewChild, HostListener, booleanAttribute, ElementRef, forwardRef, effect, contentChildren, viewChildren, model, InjectionToken, isDevMode, Injector, afterNextRender, TemplateRef } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@angular/forms';
@@ -7,7 +7,7 @@ import { NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule, FormsModule } from
7
7
  import { NgTemplateOutlet } from '@angular/common';
8
8
  import { isObservable } from 'rxjs';
9
9
 
10
- const GABARIT_VERSION = '0.7.0';
10
+ const GABARIT_VERSION = '1.0.1';
11
11
 
12
12
  const BUILT_IN_ICONS = {
13
13
  search: `<path d="m21 21-4.34-4.34" />
@@ -43,6 +43,16 @@ const BUILT_IN_ICONS = {
43
43
  <path d="M12 19V5" />`,
44
44
  'arrow-down': `<path d="M12 5v14" />
45
45
  <path d="m19 12-7 7-7-7" />`,
46
+ calendar: `<path d="M8 2v4" />
47
+ <path d="M16 2v4" />
48
+ <rect width="18" height="18" x="3" y="4" rx="2" />
49
+ <path d="M3 10h18" />`,
50
+ upload: `<path d="M12 3v12" />
51
+ <path d="m17 8-5-5-5 5" />
52
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />`,
53
+ folder: `<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />`,
54
+ file: `<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
55
+ <path d="M14 2v4a2 2 0 0 0 2 2h4" />`,
46
56
  };
47
57
 
48
58
  class IconRegistry {
@@ -114,7 +124,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
114
124
  }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-flex;flex-shrink:0;width:1.25em;height:1.25em}svg{width:100%;height:100%}\n"] }]
115
125
  }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } });
116
126
 
117
- let nextId$3 = 0;
127
+ let nextId$7 = 0;
118
128
  class AppShell {
119
129
  navLabel = input.required(/* @ts-ignore */
120
130
  ...(ngDevMode ? [{ debugName: "navLabel" }] : /* istanbul ignore next */ []));
@@ -128,12 +138,14 @@ class AppShell {
128
138
  ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
129
139
  expandLabel = input('', /* @ts-ignore */
130
140
  ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
141
+ versionLabel = input(null, /* @ts-ignore */
142
+ ...(ngDevMode ? [{ debugName: "versionLabel" }] : /* istanbul ignore next */ []));
131
143
  collapsed = input(false, /* @ts-ignore */
132
144
  ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
133
145
  collapsible = input(true, /* @ts-ignore */
134
146
  ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
135
147
  collapsedChange = output();
136
- id = ++nextId$3;
148
+ id = ++nextId$7;
137
149
  mainId = `gbt-app-shell-main-${this.id}`;
138
150
  navId = `gbt-app-shell-nav-${this.id}`;
139
151
  menuOpen = signal(false, /* @ts-ignore */
@@ -185,12 +197,12 @@ class AppShell {
185
197
  }
186
198
  }
187
199
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AppShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
188
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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}.gbt-app-shell__collapse-toggle{display:none}}@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 });
200
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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 }, versionLabel: { classPropertyName: "versionLabel", publicName: "versionLabel", 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 <div class=\"gbt-app-shell__bottom\">\n @if (versionLabel()) {\n @if (!collapsed()) {\n <div class=\"gbt-app-shell__version\">v{{ versionLabel() }}</div>\n }\n }\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 </div>\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__bottom{margin-top:auto;text-align:center;display:flex;flex-direction:column;gap:.25rem}.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__version{margin-top:auto;padding:.5rem .75rem 0;color:var(--text-secondary);font-size:.75rem}.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}.gbt-app-shell__collapse-toggle{display:none}}@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 });
189
201
  }
190
202
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AppShell, decorators: [{
191
203
  type: Component,
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}.gbt-app-shell__collapse-toggle{display:none}}@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: [{
204
+ 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 <div class=\"gbt-app-shell__bottom\">\n @if (versionLabel()) {\n @if (!collapsed()) {\n <div class=\"gbt-app-shell__version\">v{{ versionLabel() }}</div>\n }\n }\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 </div>\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__bottom{margin-top:auto;text-align:center;display:flex;flex-direction:column;gap:.25rem}.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__version{margin-top:auto;padding:.5rem .75rem 0;color:var(--text-secondary);font-size:.75rem}.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}.gbt-app-shell__collapse-toggle{display:none}}@media(prefers-reduced-motion:reduce){.gbt-app-shell__nav{transition:none}.gbt-app-shell__collapse-toggle gbt-icon{transition:none}}\n"] }]
205
+ }], 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 }] }], versionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "versionLabel", 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: [{
194
206
  type: HostListener,
195
207
  args: ['document:keydown.escape']
196
208
  }] } });
@@ -239,6 +251,135 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
239
251
  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
252
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
241
253
 
254
+ function computeInitials(name) {
255
+ const words = name.trim().split(/\s+/).filter(Boolean);
256
+ if (words.length === 0)
257
+ return '';
258
+ if (words.length === 1)
259
+ return words[0].slice(0, 2).toUpperCase();
260
+ return (words[0][0] + words[words.length - 1][0]).toUpperCase();
261
+ }
262
+ class Avatar {
263
+ name = input.required(/* @ts-ignore */
264
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
265
+ src = input(null, /* @ts-ignore */
266
+ ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
267
+ size = input('md', /* @ts-ignore */
268
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
269
+ imageFailed = signal(false, /* @ts-ignore */
270
+ ...(ngDevMode ? [{ debugName: "imageFailed" }] : /* istanbul ignore next */ []));
271
+ showImage = computed(() => !!this.src() && !this.imageFailed(), /* @ts-ignore */
272
+ ...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
273
+ initials = computed(() => computeInitials(this.name()), /* @ts-ignore */
274
+ ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
275
+ onImageError() {
276
+ this.imageFailed.set(true);
277
+ }
278
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Avatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
279
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Avatar, isStandalone: true, selector: "gbt-avatar", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-size": "size()" } }, ngImport: i0, template: "@if (showImage()) {\n <img class=\"gbt-avatar__image\" [src]=\"src()\" [alt]=\"name()\" (error)=\"onImageError()\" />\n} @else {\n <span class=\"gbt-avatar__initials\" [attr.aria-label]=\"name()\">{{ initials() }}</span>\n}\n", styles: [":host{box-sizing:border-box;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;overflow:hidden;border-radius:50%;background:var(--primary);color:var(--text-on-primary);font-weight:600;line-height:1;-webkit-user-select:none;user-select:none}:host[data-size=sm]{width:24px;height:24px;font-size:10px}:host[data-size=md]{width:32px;height:32px;font-size:13px}:host[data-size=lg]{width:48px;height:48px;font-size:18px}.gbt-avatar__image{width:100%;height:100%;object-fit:cover}.gbt-avatar__initials{display:inline-flex;align-items:center;justify-content:center}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
280
+ }
281
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Avatar, decorators: [{
282
+ type: Component,
283
+ args: [{ selector: 'gbt-avatar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
284
+ '[attr.data-size]': 'size()',
285
+ }, template: "@if (showImage()) {\n <img class=\"gbt-avatar__image\" [src]=\"src()\" [alt]=\"name()\" (error)=\"onImageError()\" />\n} @else {\n <span class=\"gbt-avatar__initials\" [attr.aria-label]=\"name()\">{{ initials() }}</span>\n}\n", styles: [":host{box-sizing:border-box;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;overflow:hidden;border-radius:50%;background:var(--primary);color:var(--text-on-primary);font-weight:600;line-height:1;-webkit-user-select:none;user-select:none}:host[data-size=sm]{width:24px;height:24px;font-size:10px}:host[data-size=md]{width:32px;height:32px;font-size:13px}:host[data-size=lg]{width:48px;height:48px;font-size:18px}.gbt-avatar__image{width:100%;height:100%;object-fit:cover}.gbt-avatar__initials{display:inline-flex;align-items:center;justify-content:center}\n"] }]
286
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
287
+
288
+ class Skeleton {
289
+ variant = input('text', /* @ts-ignore */
290
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
291
+ width = input('100%', /* @ts-ignore */
292
+ ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
293
+ height = input(null, /* @ts-ignore */
294
+ ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
295
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Skeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
296
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: Skeleton, isStandalone: true, selector: "gbt-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-variant": "variant()", "style.width": "width()", "style.height": "height()" } }, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;position:relative;overflow:hidden;background:var(--border-color);opacity:.35}:host[data-variant=text]{height:1em;border-radius:4px}:host[data-variant=circle]{aspect-ratio:1;border-radius:50%}:host[data-variant=rect]{height:100px;border-radius:var(--site-border-radius-sm)}:host:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);animation:gbt-skeleton-sweep 1.6s ease-in-out infinite}@keyframes gbt-skeleton-sweep{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
297
+ }
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Skeleton, decorators: [{
299
+ type: Component,
300
+ args: [{ selector: 'gbt-skeleton', standalone: true, template: '', changeDetection: ChangeDetectionStrategy.OnPush, host: {
301
+ '[attr.data-variant]': 'variant()',
302
+ '[style.width]': 'width()',
303
+ '[style.height]': 'height()',
304
+ 'aria-hidden': 'true',
305
+ }, styles: [":host{display:block;position:relative;overflow:hidden;background:var(--border-color);opacity:.35}:host[data-variant=text]{height:1em;border-radius:4px}:host[data-variant=circle]{aspect-ratio:1;border-radius:50%}:host[data-variant=rect]{height:100px;border-radius:var(--site-border-radius-sm)}:host:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);animation:gbt-skeleton-sweep 1.6s ease-in-out infinite}@keyframes gbt-skeleton-sweep{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}\n"] }]
306
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
307
+
308
+ class AvatarGroup {
309
+ elementRef = inject(ElementRef);
310
+ items = input.required(/* @ts-ignore */
311
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
312
+ max = input(5, /* @ts-ignore */
313
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
314
+ ariaLabel = input('Users', /* @ts-ignore */
315
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
316
+ moreLabel = input((count) => `${count} more`, /* @ts-ignore */
317
+ ...(ngDevMode ? [{ debugName: "moreLabel" }] : /* istanbul ignore next */ []));
318
+ activeItem = input(null, /* @ts-ignore */
319
+ ...(ngDevMode ? [{ debugName: "activeItem" }] : /* istanbul ignore next */ []));
320
+ itemClick = output();
321
+ panelOpen = signal(false, /* @ts-ignore */
322
+ ...(ngDevMode ? [{ debugName: "panelOpen" }] : /* istanbul ignore next */ []));
323
+ panelStyle = signal(null, /* @ts-ignore */
324
+ ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
325
+ visibleItems = computed(() => this.items().slice(0, this.max()), /* @ts-ignore */
326
+ ...(ngDevMode ? [{ debugName: "visibleItems" }] : /* istanbul ignore next */ []));
327
+ overflowItems = computed(() => this.items().slice(this.max()), /* @ts-ignore */
328
+ ...(ngDevMode ? [{ debugName: "overflowItems" }] : /* istanbul ignore next */ []));
329
+ overflowCount = computed(() => this.overflowItems().length, /* @ts-ignore */
330
+ ...(ngDevMode ? [{ debugName: "overflowCount" }] : /* istanbul ignore next */ []));
331
+ isActive(item) {
332
+ return this.activeItem() === item;
333
+ }
334
+ selectItem(item) {
335
+ this.itemClick.emit(item);
336
+ this.panelOpen.set(false);
337
+ }
338
+ toggleOverflowPanel() {
339
+ this.panelOpen.update((value) => !value);
340
+ if (this.panelOpen()) {
341
+ this.updatePanelPosition();
342
+ }
343
+ }
344
+ updatePanelPosition() {
345
+ if (!this.panelOpen()) {
346
+ return;
347
+ }
348
+ const trigger = this.elementRef.nativeElement.querySelector('.gbt-avatar-group__more');
349
+ if (!trigger) {
350
+ return;
351
+ }
352
+ const rect = trigger.getBoundingClientRect();
353
+ this.panelStyle.set({
354
+ top: `${rect.bottom + 6}px`,
355
+ left: `${rect.left}px`,
356
+ });
357
+ }
358
+ handleClickOutside(event) {
359
+ if (this.panelOpen() && !this.elementRef.nativeElement.contains(event.target)) {
360
+ this.panelOpen.set(false);
361
+ }
362
+ }
363
+ onKeydown(event) {
364
+ if (event.key === 'Escape' && this.panelOpen()) {
365
+ event.preventDefault();
366
+ event.stopPropagation();
367
+ this.panelOpen.set(false);
368
+ }
369
+ }
370
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AvatarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
371
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: AvatarGroup, isStandalone: true, selector: "gbt-avatar-group", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, moreLabel: { classPropertyName: "moreLabel", publicName: "moreLabel", isSignal: true, isRequired: false, transformFunction: null }, activeItem: { classPropertyName: "activeItem", publicName: "activeItem", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { listeners: { "document:click": "handleClickOutside($event)", "keydown": "onKeydown($event)", "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" } }, ngImport: i0, template: "<ul class=\"gbt-avatar-group__list\" [attr.aria-label]=\"ariaLabel()\">\n @for (item of visibleItems(); track $index) {\n <li class=\"gbt-avatar-group__item\">\n <button\n type=\"button\"\n class=\"gbt-avatar-group__button\"\n [class.gbt-avatar-group__button--active]=\"isActive(item)\"\n [attr.aria-label]=\"item.name\"\n [attr.aria-current]=\"isActive(item) ? 'true' : null\"\n (click)=\"selectItem(item)\"\n >\n <gbt-avatar [name]=\"item.name\" [src]=\"item.src ?? null\" size=\"md\" />\n </button>\n </li>\n }\n @if (overflowCount() > 0) {\n <li class=\"gbt-avatar-group__item\">\n <button\n type=\"button\"\n class=\"gbt-avatar-group__more\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"panelOpen()\"\n [attr.aria-label]=\"moreLabel()(overflowCount())\"\n (click)=\"toggleOverflowPanel()\"\n >\n +{{ overflowCount() }}\n </button>\n </li>\n }\n</ul>\n\n@if (panelOpen() && panelStyle(); as style) {\n <ul\n class=\"gbt-avatar-group__panel\"\n role=\"menu\"\n [attr.aria-label]=\"moreLabel()(overflowCount())\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n >\n @for (item of overflowItems(); track $index) {\n <li role=\"presentation\">\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"gbt-avatar-group__panel-item\"\n [attr.aria-current]=\"isActive(item) ? 'true' : null\"\n (click)=\"selectItem(item)\"\n >\n <gbt-avatar [name]=\"item.name\" [src]=\"item.src ?? null\" size=\"sm\" />\n <span class=\"gbt-avatar-group__panel-item-name\">{{ item.name }}</span>\n @if (isActive(item)) {\n <gbt-icon name=\"check\" class=\"gbt-avatar-group__panel-item-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n}\n", styles: [":host{display:inline-flex}.gbt-avatar-group__list{display:flex;align-items:center;margin:0;padding:0;list-style:none}.gbt-avatar-group__item{display:flex}.gbt-avatar-group__item:not(:first-child){margin-left:-8px}.gbt-avatar-group__button,.gbt-avatar-group__more{position:relative;box-sizing:border-box;display:inline-flex;padding:0;border:none;border-radius:50%;background:none;cursor:pointer;box-shadow:0 0 0 2px var(--bg-principal);transition:transform .12s cubic-bezier(.4,0,.2,1)}.gbt-avatar-group__button:hover,.gbt-avatar-group__button:focus-visible,.gbt-avatar-group__more:hover,.gbt-avatar-group__more:focus-visible{z-index:1;transform:translateY(-2px)}.gbt-avatar-group__button:focus-visible,.gbt-avatar-group__more:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-avatar-group__button--active{box-shadow:0 0 0 2px var(--bg-principal),0 0 0 4px var(--primary)}.gbt-avatar-group__more{align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-panel);color:var(--text-secondary);font-size:12px;font-weight:600}.gbt-avatar-group__panel{box-sizing:border-box;position:fixed;z-index:1000;margin:0;padding:6px;max-height:280px;overflow-y:auto;list-style:none;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-avatar-group-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-avatar-group__panel::-webkit-scrollbar{width:6px}.gbt-avatar-group__panel::-webkit-scrollbar-track{background:transparent}.gbt-avatar-group__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-avatar-group__panel-item{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:6px 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-avatar-group__panel-item:hover,.gbt-avatar-group__panel-item:focus-visible{background:var(--bg-hover)}.gbt-avatar-group__panel-item-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gbt-avatar-group__panel-item-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-avatar-group-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-avatar-group__panel{animation:none}.gbt-avatar-group__button,.gbt-avatar-group__more{transition:none}}\n"], dependencies: [{ kind: "component", type: Avatar, selector: "gbt-avatar", inputs: ["name", "src", "size"] }, { kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
372
+ }
373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AvatarGroup, decorators: [{
374
+ type: Component,
375
+ args: [{ selector: 'gbt-avatar-group', standalone: true, imports: [Avatar, Icon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
376
+ '(document:click)': 'handleClickOutside($event)',
377
+ '(keydown)': 'onKeydown($event)',
378
+ '(window:scroll)': 'updatePanelPosition()',
379
+ '(window:resize)': 'updatePanelPosition()',
380
+ }, template: "<ul class=\"gbt-avatar-group__list\" [attr.aria-label]=\"ariaLabel()\">\n @for (item of visibleItems(); track $index) {\n <li class=\"gbt-avatar-group__item\">\n <button\n type=\"button\"\n class=\"gbt-avatar-group__button\"\n [class.gbt-avatar-group__button--active]=\"isActive(item)\"\n [attr.aria-label]=\"item.name\"\n [attr.aria-current]=\"isActive(item) ? 'true' : null\"\n (click)=\"selectItem(item)\"\n >\n <gbt-avatar [name]=\"item.name\" [src]=\"item.src ?? null\" size=\"md\" />\n </button>\n </li>\n }\n @if (overflowCount() > 0) {\n <li class=\"gbt-avatar-group__item\">\n <button\n type=\"button\"\n class=\"gbt-avatar-group__more\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"panelOpen()\"\n [attr.aria-label]=\"moreLabel()(overflowCount())\"\n (click)=\"toggleOverflowPanel()\"\n >\n +{{ overflowCount() }}\n </button>\n </li>\n }\n</ul>\n\n@if (panelOpen() && panelStyle(); as style) {\n <ul\n class=\"gbt-avatar-group__panel\"\n role=\"menu\"\n [attr.aria-label]=\"moreLabel()(overflowCount())\"\n [style.top]=\"style.top\"\n [style.left]=\"style.left\"\n >\n @for (item of overflowItems(); track $index) {\n <li role=\"presentation\">\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"gbt-avatar-group__panel-item\"\n [attr.aria-current]=\"isActive(item) ? 'true' : null\"\n (click)=\"selectItem(item)\"\n >\n <gbt-avatar [name]=\"item.name\" [src]=\"item.src ?? null\" size=\"sm\" />\n <span class=\"gbt-avatar-group__panel-item-name\">{{ item.name }}</span>\n @if (isActive(item)) {\n <gbt-icon name=\"check\" class=\"gbt-avatar-group__panel-item-check\" aria-hidden=\"true\" />\n }\n </button>\n </li>\n }\n </ul>\n}\n", styles: [":host{display:inline-flex}.gbt-avatar-group__list{display:flex;align-items:center;margin:0;padding:0;list-style:none}.gbt-avatar-group__item{display:flex}.gbt-avatar-group__item:not(:first-child){margin-left:-8px}.gbt-avatar-group__button,.gbt-avatar-group__more{position:relative;box-sizing:border-box;display:inline-flex;padding:0;border:none;border-radius:50%;background:none;cursor:pointer;box-shadow:0 0 0 2px var(--bg-principal);transition:transform .12s cubic-bezier(.4,0,.2,1)}.gbt-avatar-group__button:hover,.gbt-avatar-group__button:focus-visible,.gbt-avatar-group__more:hover,.gbt-avatar-group__more:focus-visible{z-index:1;transform:translateY(-2px)}.gbt-avatar-group__button:focus-visible,.gbt-avatar-group__more:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-avatar-group__button--active{box-shadow:0 0 0 2px var(--bg-principal),0 0 0 4px var(--primary)}.gbt-avatar-group__more{align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-panel);color:var(--text-secondary);font-size:12px;font-weight:600}.gbt-avatar-group__panel{box-sizing:border-box;position:fixed;z-index:1000;margin:0;padding:6px;max-height:280px;overflow-y:auto;list-style:none;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-avatar-group-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-avatar-group__panel::-webkit-scrollbar{width:6px}.gbt-avatar-group__panel::-webkit-scrollbar-track{background:transparent}.gbt-avatar-group__panel::-webkit-scrollbar-thumb{background:var(--bg-hover);border-radius:3px}.gbt-avatar-group__panel-item{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:6px 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-avatar-group__panel-item:hover,.gbt-avatar-group__panel-item:focus-visible{background:var(--bg-hover)}.gbt-avatar-group__panel-item-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gbt-avatar-group__panel-item-check{flex-shrink:0;color:var(--primary)}@keyframes gbt-avatar-group-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-avatar-group__panel{animation:none}.gbt-avatar-group__button,.gbt-avatar-group__more{transition:none}}\n"] }]
381
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], moreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreLabel", required: false }] }], activeItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeItem", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
382
+
242
383
  const ASSERTIVE_VARIANTS$1 = new Set(['warning', 'error']);
243
384
  const VARIANT_ICONS$1 = {
244
385
  success: 'check-circle',
@@ -323,6 +464,8 @@ class Tag {
323
464
  ...(ngDevMode ? [{ debugName: "removable" }] : /* istanbul ignore next */ []));
324
465
  removeLabel = input('Remove', /* @ts-ignore */
325
466
  ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
467
+ disabled = input(false, /* @ts-ignore */
468
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
326
469
  removed = output();
327
470
  textColor = computed(() => getReadableTextColor(this.color()), /* @ts-ignore */
328
471
  ...(ngDevMode ? [{ debugName: "textColor" }] : /* istanbul ignore next */ []));
@@ -331,12 +474,12 @@ class Tag {
331
474
  this.removed.emit();
332
475
  }
333
476
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tag, deps: [], target: i0.ɵɵFactoryTarget.Component });
334
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Tag, isStandalone: true, selector: "gbt-tag", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: true, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, ngImport: i0, template: "<span class=\"gbt-tag\" [style.background]=\"color()\" [style.color]=\"textColor()\">\n <span class=\"gbt-tag__label\"><ng-content /></span>\n @if (removable()) {\n <button type=\"button\" class=\"gbt-tag__remove\" [attr.aria-label]=\"removeLabel()\" (click)=\"onRemoveClick($event)\">\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</span>\n", styles: [":host{display:inline-flex;max-width:100%}.gbt-tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--site-border-radius-sm);font-size:.75rem;font-weight:600;line-height:1.4;max-width:100%}.gbt-tag__label{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-tag__remove{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;background:transparent;border:none;border-radius:4px;color:currentColor;cursor:pointer;transition:background var(--site-transition-fast)}.gbt-tag__remove:hover{background:color-mix(in srgb,currentColor 20%,transparent)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
477
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Tag, isStandalone: true, selector: "gbt-tag", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: true, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, ngImport: i0, template: "<span\n class=\"gbt-tag\"\n [style.background]=\"color()\"\n [style.color]=\"textColor()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n>\n <span class=\"gbt-tag__label\"><ng-content /></span>\n @if (removable()) {\n <button type=\"button\" class=\"gbt-tag__remove\" [attr.aria-label]=\"removeLabel()\" (click)=\"onRemoveClick($event)\">\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</span>\n", styles: [":host{display:inline-flex;max-width:100%}.gbt-tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--site-border-radius-sm);font-size:.75rem;font-weight:600;line-height:1.4;max-width:100%}.gbt-tag__label{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-tag__remove{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;background:transparent;border:none;border-radius:4px;color:currentColor;cursor:pointer;transition:background var(--site-transition-fast)}.gbt-tag__remove:hover{background:color-mix(in srgb,currentColor 20%,transparent)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
335
478
  }
336
479
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tag, decorators: [{
337
480
  type: Component,
338
- args: [{ selector: 'gbt-tag', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"gbt-tag\" [style.background]=\"color()\" [style.color]=\"textColor()\">\n <span class=\"gbt-tag__label\"><ng-content /></span>\n @if (removable()) {\n <button type=\"button\" class=\"gbt-tag__remove\" [attr.aria-label]=\"removeLabel()\" (click)=\"onRemoveClick($event)\">\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</span>\n", styles: [":host{display:inline-flex;max-width:100%}.gbt-tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--site-border-radius-sm);font-size:.75rem;font-weight:600;line-height:1.4;max-width:100%}.gbt-tag__label{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-tag__remove{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;background:transparent;border:none;border-radius:4px;color:currentColor;cursor:pointer;transition:background var(--site-transition-fast)}.gbt-tag__remove:hover{background:color-mix(in srgb,currentColor 20%,transparent)}\n"] }]
339
- }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: true }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
481
+ args: [{ selector: 'gbt-tag', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span\n class=\"gbt-tag\"\n [style.background]=\"color()\"\n [style.color]=\"textColor()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n>\n <span class=\"gbt-tag__label\"><ng-content /></span>\n @if (removable()) {\n <button type=\"button\" class=\"gbt-tag__remove\" [attr.aria-label]=\"removeLabel()\" (click)=\"onRemoveClick($event)\">\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n }\n</span>\n", styles: [":host{display:inline-flex;max-width:100%}.gbt-tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--site-border-radius-sm);font-size:.75rem;font-weight:600;line-height:1.4;max-width:100%}.gbt-tag__label{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gbt-tag__remove{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;background:transparent;border:none;border-radius:4px;color:currentColor;cursor:pointer;transition:background var(--site-transition-fast)}.gbt-tag__remove:hover{background:color-mix(in srgb,currentColor 20%,transparent)}\n"] }]
482
+ }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: true }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
340
483
 
341
484
  class EmptyState {
342
485
  illustration = input.required(/* @ts-ignore */
@@ -667,7 +810,7 @@ class Select {
667
810
  useExisting: forwardRef(() => Select),
668
811
  multi: true,
669
812
  },
670
- ], 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]=\"describedBy()\"\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 (chipsVisible()) {\n <div class=\"gbt-select__chips\" [id]=\"chipsId()\">\n @for (option of selectedOptions(); track option.value; let i = $index) {\n <gbt-tag\n [color]=\"option.color ?? '#6b7280'\"\n [removable]=\"!isDisabled()\"\n [removeLabel]=\"chipRemoveLabel()(option.label)\"\n (removed)=\"removeChip(option.value, i)\"\n >\n {{ option.label }}\n </gbt-tag>\n }\n </div>\n }\n @if (chips() && multiple()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ selectedCountLabel()(selectedOptions().length) }}\n </div>\n }\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__chips{display:flex;flex-wrap:wrap;gap:4px}.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}.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"] }, { kind: "component", type: Tag, selector: "gbt-tag", inputs: ["color", "removable", "removeLabel"], outputs: ["removed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
813
+ ], 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]=\"describedBy()\"\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 (chipsVisible()) {\n <div class=\"gbt-select__chips\" [id]=\"chipsId()\">\n @for (option of selectedOptions(); track option.value; let i = $index) {\n <gbt-tag\n [color]=\"option.color ?? '#6b7280'\"\n [removable]=\"!isDisabled()\"\n [disabled]=\"isDisabled()\"\n [removeLabel]=\"chipRemoveLabel()(option.label)\"\n (removed)=\"removeChip(option.value, i)\"\n >\n {{ option.label }}\n </gbt-tag>\n }\n </div>\n }\n @if (chips() && multiple()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ selectedCountLabel()(selectedOptions().length) }}\n </div>\n }\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__chips{display:flex;flex-wrap:wrap;gap:4px}.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}.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"] }, { kind: "component", type: Tag, selector: "gbt-tag", inputs: ["color", "removable", "removeLabel", "disabled"], outputs: ["removed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
671
814
  }
672
815
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Select, decorators: [{
673
816
  type: Component,
@@ -683,7 +826,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
683
826
  useExisting: forwardRef(() => Select),
684
827
  multi: true,
685
828
  },
686
- ], 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]=\"describedBy()\"\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 (chipsVisible()) {\n <div class=\"gbt-select__chips\" [id]=\"chipsId()\">\n @for (option of selectedOptions(); track option.value; let i = $index) {\n <gbt-tag\n [color]=\"option.color ?? '#6b7280'\"\n [removable]=\"!isDisabled()\"\n [removeLabel]=\"chipRemoveLabel()(option.label)\"\n (removed)=\"removeChip(option.value, i)\"\n >\n {{ option.label }}\n </gbt-tag>\n }\n </div>\n }\n @if (chips() && multiple()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ selectedCountLabel()(selectedOptions().length) }}\n </div>\n }\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__chips{display:flex;flex-wrap:wrap;gap:4px}.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}.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"] }]
829
+ ], 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]=\"describedBy()\"\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 (chipsVisible()) {\n <div class=\"gbt-select__chips\" [id]=\"chipsId()\">\n @for (option of selectedOptions(); track option.value; let i = $index) {\n <gbt-tag\n [color]=\"option.color ?? '#6b7280'\"\n [removable]=\"!isDisabled()\"\n [disabled]=\"isDisabled()\"\n [removeLabel]=\"chipRemoveLabel()(option.label)\"\n (removed)=\"removeChip(option.value, i)\"\n >\n {{ option.label }}\n </gbt-tag>\n }\n </div>\n }\n @if (chips() && multiple()) {\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">\n {{ selectedCountLabel()(selectedOptions().length) }}\n </div>\n }\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__chips{display:flex;flex-wrap:wrap;gap:4px}.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}.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"] }]
687
830
  }], 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 }] }], chips: [{ type: i0.Input, args: [{ isSignal: true, alias: "chips", 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 }] }], chipRemoveLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "chipRemoveLabel", required: false }] }] } });
688
831
 
689
832
  class ListToolbar {
@@ -884,6 +1027,99 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
884
1027
  args: ['document:keydown.escape']
885
1028
  }] } });
886
1029
 
1030
+ const CLOSE_ANIMATION_MS = 200;
1031
+ class Drawer {
1032
+ isOpen = input.required(/* @ts-ignore */
1033
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1034
+ edge = input('right', /* @ts-ignore */
1035
+ ...(ngDevMode ? [{ debugName: "edge" }] : /* istanbul ignore next */ []));
1036
+ heading = input('', /* @ts-ignore */
1037
+ ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
1038
+ headingLevel = input(2, /* @ts-ignore */
1039
+ ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
1040
+ closeLabel = input('Close', /* @ts-ignore */
1041
+ ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
1042
+ closed = output();
1043
+ rendered = signal(false, /* @ts-ignore */
1044
+ ...(ngDevMode ? [{ debugName: "rendered" }] : /* istanbul ignore next */ []));
1045
+ panel = viewChild('panel', /* @ts-ignore */
1046
+ ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
1047
+ previouslyFocused = null;
1048
+ closeTimer = null;
1049
+ constructor() {
1050
+ effect(() => {
1051
+ if (this.isOpen()) {
1052
+ if (this.closeTimer !== null) {
1053
+ clearTimeout(this.closeTimer);
1054
+ this.closeTimer = null;
1055
+ }
1056
+ this.rendered.set(true);
1057
+ this.previouslyFocused = document.activeElement;
1058
+ queueMicrotask(() => this.panel()?.nativeElement.focus());
1059
+ }
1060
+ else if (this.rendered()) {
1061
+ this.closeTimer = setTimeout(() => {
1062
+ this.closeTimer = null;
1063
+ this.rendered.set(false);
1064
+ if (this.previouslyFocused) {
1065
+ const target = this.previouslyFocused;
1066
+ this.previouslyFocused = null;
1067
+ target.focus();
1068
+ }
1069
+ }, CLOSE_ANIMATION_MS);
1070
+ }
1071
+ });
1072
+ }
1073
+ ngOnDestroy() {
1074
+ if (this.closeTimer !== null) {
1075
+ clearTimeout(this.closeTimer);
1076
+ }
1077
+ this.previouslyFocused?.focus();
1078
+ }
1079
+ onEscape() {
1080
+ if (this.isOpen()) {
1081
+ this.closed.emit();
1082
+ }
1083
+ }
1084
+ onBackdropClick(event) {
1085
+ if (event.target === event.currentTarget) {
1086
+ this.closed.emit();
1087
+ }
1088
+ }
1089
+ onPanelKeydown(event) {
1090
+ if (event.key !== 'Tab') {
1091
+ return;
1092
+ }
1093
+ const panel = this.panel()?.nativeElement;
1094
+ if (!panel) {
1095
+ return;
1096
+ }
1097
+ const focusable = panel.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
1098
+ if (focusable.length === 0) {
1099
+ return;
1100
+ }
1101
+ const first = focusable[0];
1102
+ const last = focusable[focusable.length - 1];
1103
+ if (event.shiftKey && document.activeElement === first) {
1104
+ event.preventDefault();
1105
+ last.focus();
1106
+ }
1107
+ else if (!event.shiftKey && document.activeElement === last) {
1108
+ event.preventDefault();
1109
+ first.focus();
1110
+ }
1111
+ }
1112
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Drawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1113
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Drawer, isStandalone: true, selector: "gbt-drawer", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, edge: { classPropertyName: "edge", publicName: "edge", isSignal: true, isRequired: false, 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: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (rendered()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"gbt-drawer__backdrop\"\n [class.gbt-drawer__backdrop--closing]=\"!isOpen()\"\n (click)=\"onBackdropClick($event)\"\n >\n <div\n #panel\n class=\"gbt-drawer__panel\"\n [class.gbt-drawer__panel--closing]=\"!isOpen()\"\n [attr.data-edge]=\"edge()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n <header class=\"gbt-drawer__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-drawer__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-drawer__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-drawer__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-drawer__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-drawer__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-drawer__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-drawer__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-drawer__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-drawer__backdrop{position:fixed;inset:0;background:#0006;z-index:1200;animation:gbt-drawer-backdrop-in .2s ease-out}.gbt-drawer__backdrop--closing{animation:gbt-drawer-backdrop-out .2s ease-in forwards}.gbt-drawer__panel{position:fixed;display:flex;flex-direction:column;background:var(--bg-principal);box-shadow:var(--site-shadow-lg)}.gbt-drawer__panel:focus{outline:none}.gbt-drawer__panel:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-drawer__panel[data-edge=right]{top:0;right:0;bottom:0;width:min(90vw,400px);animation:gbt-drawer-slide-in-right .2s ease-out}.gbt-drawer__panel[data-edge=right].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-right .2s ease-in forwards}.gbt-drawer__panel[data-edge=left]{top:0;left:0;bottom:0;width:min(90vw,400px);animation:gbt-drawer-slide-in-left .2s ease-out}.gbt-drawer__panel[data-edge=left].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-left .2s ease-in forwards}.gbt-drawer__panel[data-edge=top]{top:0;left:0;right:0;height:min(90vh,400px);animation:gbt-drawer-slide-in-top .2s ease-out}.gbt-drawer__panel[data-edge=top].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-top .2s ease-in forwards}.gbt-drawer__panel[data-edge=bottom]{bottom:0;left:0;right:0;height:min(90vh,400px);animation:gbt-drawer-slide-in-bottom .2s ease-out}.gbt-drawer__panel[data-edge=bottom].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-bottom .2s ease-in forwards}.gbt-drawer__header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-drawer__header .gbt-drawer__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-drawer__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-drawer__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-drawer__body{flex:1;min-height:0;padding:1.25rem;overflow-y:auto;display:flex;flex-direction:column;gap:1rem}@keyframes gbt-drawer-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-drawer-backdrop-out{0%{opacity:1}to{opacity:0}}@keyframes gbt-drawer-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes gbt-drawer-slide-out-right{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes gbt-drawer-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes gbt-drawer-slide-out-left{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes gbt-drawer-slide-in-top{0%{transform:translateY(-100%)}to{transform:translateY(0)}}@keyframes gbt-drawer-slide-out-top{0%{transform:translateY(0)}to{transform:translateY(-100%)}}@keyframes gbt-drawer-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes gbt-drawer-slide-out-bottom{0%{transform:translateY(0)}to{transform:translateY(100%)}}@media(prefers-reduced-motion:reduce){.gbt-drawer__backdrop,.gbt-drawer__backdrop--closing,.gbt-drawer__panel,.gbt-drawer__panel--closing{animation:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1114
+ }
1115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Drawer, decorators: [{
1116
+ type: Component,
1117
+ args: [{ selector: 'gbt-drawer', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (rendered()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"gbt-drawer__backdrop\"\n [class.gbt-drawer__backdrop--closing]=\"!isOpen()\"\n (click)=\"onBackdropClick($event)\"\n >\n <div\n #panel\n class=\"gbt-drawer__panel\"\n [class.gbt-drawer__panel--closing]=\"!isOpen()\"\n [attr.data-edge]=\"edge()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"heading() || null\"\n tabindex=\"-1\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n <header class=\"gbt-drawer__header\">\n @switch (headingLevel()) {\n @case (1) {\n <h1 class=\"gbt-drawer__title\">{{ heading() }}</h1>\n }\n @case (3) {\n <h3 class=\"gbt-drawer__title\">{{ heading() }}</h3>\n }\n @case (4) {\n <h4 class=\"gbt-drawer__title\">{{ heading() }}</h4>\n }\n @case (5) {\n <h5 class=\"gbt-drawer__title\">{{ heading() }}</h5>\n }\n @case (6) {\n <h6 class=\"gbt-drawer__title\">{{ heading() }}</h6>\n }\n @default {\n <h2 class=\"gbt-drawer__title\">{{ heading() }}</h2>\n }\n }\n <button\n type=\"button\"\n class=\"gbt-drawer__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-drawer__body\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".gbt-drawer__backdrop{position:fixed;inset:0;background:#0006;z-index:1200;animation:gbt-drawer-backdrop-in .2s ease-out}.gbt-drawer__backdrop--closing{animation:gbt-drawer-backdrop-out .2s ease-in forwards}.gbt-drawer__panel{position:fixed;display:flex;flex-direction:column;background:var(--bg-principal);box-shadow:var(--site-shadow-lg)}.gbt-drawer__panel:focus{outline:none}.gbt-drawer__panel:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-drawer__panel[data-edge=right]{top:0;right:0;bottom:0;width:min(90vw,400px);animation:gbt-drawer-slide-in-right .2s ease-out}.gbt-drawer__panel[data-edge=right].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-right .2s ease-in forwards}.gbt-drawer__panel[data-edge=left]{top:0;left:0;bottom:0;width:min(90vw,400px);animation:gbt-drawer-slide-in-left .2s ease-out}.gbt-drawer__panel[data-edge=left].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-left .2s ease-in forwards}.gbt-drawer__panel[data-edge=top]{top:0;left:0;right:0;height:min(90vh,400px);animation:gbt-drawer-slide-in-top .2s ease-out}.gbt-drawer__panel[data-edge=top].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-top .2s ease-in forwards}.gbt-drawer__panel[data-edge=bottom]{bottom:0;left:0;right:0;height:min(90vh,400px);animation:gbt-drawer-slide-in-bottom .2s ease-out}.gbt-drawer__panel[data-edge=bottom].gbt-drawer__panel--closing{animation:gbt-drawer-slide-out-bottom .2s ease-in forwards}.gbt-drawer__header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:1rem 1.25rem;border-bottom:1px solid var(--border-color)}.gbt-drawer__header .gbt-drawer__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.gbt-drawer__close{position:relative;display:inline-flex;background:none;border:none;color:var(--text-discret);cursor:pointer}.gbt-drawer__close:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-drawer__body{flex:1;min-height:0;padding:1.25rem;overflow-y:auto;display:flex;flex-direction:column;gap:1rem}@keyframes gbt-drawer-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-drawer-backdrop-out{0%{opacity:1}to{opacity:0}}@keyframes gbt-drawer-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes gbt-drawer-slide-out-right{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes gbt-drawer-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes gbt-drawer-slide-out-left{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes gbt-drawer-slide-in-top{0%{transform:translateY(-100%)}to{transform:translateY(0)}}@keyframes gbt-drawer-slide-out-top{0%{transform:translateY(0)}to{transform:translateY(-100%)}}@keyframes gbt-drawer-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes gbt-drawer-slide-out-bottom{0%{transform:translateY(0)}to{transform:translateY(100%)}}@media(prefers-reduced-motion:reduce){.gbt-drawer__backdrop,.gbt-drawer__backdrop--closing,.gbt-drawer__panel,.gbt-drawer__panel--closing{animation:none}}\n"] }]
1118
+ }], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: true }] }], edge: [{ type: i0.Input, args: [{ isSignal: true, alias: "edge", required: false }] }], 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"] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], onEscape: [{
1119
+ type: HostListener,
1120
+ args: ['document:keydown.escape']
1121
+ }] } });
1122
+
887
1123
  class Table {
888
1124
  data = input.required(/* @ts-ignore */
889
1125
  ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -1377,6 +1613,35 @@ function areaPath(points, baseline) {
1377
1613
  const first = points[0];
1378
1614
  return `${linePath(points)}L${round(last.x)},${round(baseline)}L${round(first.x)},${round(baseline)}Z`;
1379
1615
  }
1616
+ function arcPoint(radius, angle) {
1617
+ return { x: radius * Math.sin(angle), y: -radius * Math.cos(angle) };
1618
+ }
1619
+ function point(p) {
1620
+ return `${round(p.x)},${round(p.y)}`;
1621
+ }
1622
+ const FULL_CIRCLE = Math.PI * 2;
1623
+ function arcPath(arc) {
1624
+ const { startAngle, endAngle, innerRadius, outerRadius } = arc;
1625
+ const span = endAngle - startAngle;
1626
+ if (span <= 0)
1627
+ return '';
1628
+ if (span >= FULL_CIRCLE - 1e-9) {
1629
+ const mid = startAngle + Math.PI;
1630
+ return (arcPath({ startAngle, endAngle: mid, innerRadius, outerRadius }) +
1631
+ arcPath({ startAngle: mid, endAngle: startAngle + FULL_CIRCLE, innerRadius, outerRadius }));
1632
+ }
1633
+ const largeArc = span > Math.PI ? 1 : 0;
1634
+ const outerStart = arcPoint(outerRadius, startAngle);
1635
+ const outerEnd = arcPoint(outerRadius, endAngle);
1636
+ const outerArc = `A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc},1 ${point(outerEnd)}`;
1637
+ if (innerRadius <= 0) {
1638
+ return `M0,0L${point(outerStart)}${outerArc}Z`;
1639
+ }
1640
+ const innerStart = arcPoint(innerRadius, startAngle);
1641
+ const innerEnd = arcPoint(innerRadius, endAngle);
1642
+ const innerArc = `A${round(innerRadius)},${round(innerRadius)} 0 ${largeArc},0 ${point(innerStart)}`;
1643
+ return `M${point(outerStart)}${outerArc}L${point(innerEnd)}${innerArc}Z`;
1644
+ }
1380
1645
 
1381
1646
  function nearestIndex(sorted, target) {
1382
1647
  if (sorted.length === 0)
@@ -1761,16 +2026,26 @@ const DASH_ARRAYS$1 = {
1761
2026
  class ChartLegend {
1762
2027
  entries = input.required(/* @ts-ignore */
1763
2028
  ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
2029
+ interactive = input(false, { ...(ngDevMode ? { debugName: "interactive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2030
+ activeIndex = input(null, /* @ts-ignore */
2031
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
2032
+ activeIndexChange = output();
1764
2033
  dashArray(pattern) {
1765
2034
  return DASH_ARRAYS$1[pattern ?? 'solid'];
1766
2035
  }
2036
+ onMouseLeave(event) {
2037
+ const target = event.currentTarget;
2038
+ if (target.ownerDocument.activeElement === target)
2039
+ return;
2040
+ this.activeIndexChange.emit(null);
2041
+ }
1767
2042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartLegend, deps: [], target: i0.ɵɵFactoryTarget.Component });
1768
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ChartLegend, isStandalone: true, selector: "gbt-chart-legend", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ul class=\"gbt-chart-legend\">\n @for (entry of entries(); track $index) {\n <li class=\"gbt-chart-legend__item\" [attr.data-pattern]=\"entry.pattern ?? 'solid'\">\n <svg class=\"gbt-chart-legend__swatch\" viewBox=\"0 0 24 8\" aria-hidden=\"true\" focusable=\"false\">\n <line\n class=\"gbt-chart-legend__line\"\n x1=\"0\"\n y1=\"4\"\n x2=\"24\"\n y2=\"4\"\n [attr.stroke-dasharray]=\"dashArray(entry.pattern)\"\n stroke-width=\"2\"\n />\n </svg>\n {{ entry.label }}\n @if (entry.value; as value) {\n <span class=\"gbt-chart-legend__value\">{{ value }}</span>\n }\n </li>\n }\n</ul>\n", styles: [".gbt-chart-legend{display:flex;flex-wrap:wrap;gap:.75rem 1.25rem;margin:0;padding:0;list-style:none;font-size:.8125rem;color:var(--text-secondary)}.gbt-chart-legend__item{display:inline-flex;align-items:center;gap:.375rem}.gbt-chart-legend__item:nth-child(3n+1) .gbt-chart-legend__line{stroke:var(--chart-series-1-base)}.gbt-chart-legend__item:nth-child(3n+2) .gbt-chart-legend__line{stroke:var(--chart-series-2-base)}.gbt-chart-legend__item:nth-child(3n+3) .gbt-chart-legend__line{stroke:var(--chart-series-3-base)}.gbt-chart-legend__swatch{width:1.5rem;height:.5rem;flex:none}.gbt-chart-legend__value{margin-left:.375rem;font-variant-numeric:tabular-nums;font-weight:600;color:var(--text-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ChartLegend, isStandalone: true, selector: "gbt-chart-legend", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: true, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndexChange: "activeIndexChange" }, ngImport: i0, template: "<ul class=\"gbt-chart-legend\">\n @for (entry of entries(); track $index) {\n <li\n class=\"gbt-chart-legend__item\"\n [class.gbt-chart-legend__item--active]=\"interactive() && activeIndex() === $index\"\n [attr.data-pattern]=\"entry.pattern ?? 'solid'\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n (mouseenter)=\"interactive() && activeIndexChange.emit($index)\"\n (mouseleave)=\"interactive() && onMouseLeave($event)\"\n (focus)=\"interactive() && activeIndexChange.emit($index)\"\n (blur)=\"interactive() && activeIndexChange.emit(null)\"\n >\n <svg class=\"gbt-chart-legend__swatch\" viewBox=\"0 0 24 8\" aria-hidden=\"true\" focusable=\"false\">\n @if (entry.color; as color) {\n <rect class=\"gbt-chart-legend__fill\" x=\"4\" y=\"0\" width=\"8\" height=\"8\" rx=\"2\" [attr.fill]=\"color\" />\n } @else {\n <line\n class=\"gbt-chart-legend__line\"\n x1=\"0\"\n y1=\"4\"\n x2=\"24\"\n y2=\"4\"\n [attr.stroke-dasharray]=\"dashArray(entry.pattern)\"\n stroke-width=\"2\"\n />\n }\n </svg>\n {{ entry.label }}\n @if (entry.value; as value) {\n <span class=\"gbt-chart-legend__value\">{{ value }}</span>\n }\n </li>\n }\n</ul>\n", styles: [".gbt-chart-legend{display:flex;flex-wrap:wrap;gap:.75rem 1.25rem;margin:0;padding:0;list-style:none;font-size:.8125rem;color:var(--text-secondary)}.gbt-chart-legend__item{display:inline-flex;align-items:center;gap:.375rem;border-radius:var(--site-border-radius-sm)}.gbt-chart-legend__item:nth-child(3n+1) .gbt-chart-legend__line{stroke:var(--chart-series-1-base)}.gbt-chart-legend__item:nth-child(3n+2) .gbt-chart-legend__line{stroke:var(--chart-series-2-base)}.gbt-chart-legend__item:nth-child(3n+3) .gbt-chart-legend__line{stroke:var(--chart-series-3-base)}.gbt-chart-legend__item[tabindex]{cursor:default;padding:.125rem .25rem;margin:-.125rem -.25rem}.gbt-chart-legend__item[tabindex]:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-chart-legend__item--active{background:var(--bg-hover)}.gbt-chart-legend__swatch{width:1.5rem;height:.5rem;flex:none}.gbt-chart-legend__value{margin-left:.375rem;font-variant-numeric:tabular-nums;font-weight:600;color:var(--text-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1769
2044
  }
1770
2045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartLegend, decorators: [{
1771
2046
  type: Component,
1772
- args: [{ selector: 'gbt-chart-legend', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"gbt-chart-legend\">\n @for (entry of entries(); track $index) {\n <li class=\"gbt-chart-legend__item\" [attr.data-pattern]=\"entry.pattern ?? 'solid'\">\n <svg class=\"gbt-chart-legend__swatch\" viewBox=\"0 0 24 8\" aria-hidden=\"true\" focusable=\"false\">\n <line\n class=\"gbt-chart-legend__line\"\n x1=\"0\"\n y1=\"4\"\n x2=\"24\"\n y2=\"4\"\n [attr.stroke-dasharray]=\"dashArray(entry.pattern)\"\n stroke-width=\"2\"\n />\n </svg>\n {{ entry.label }}\n @if (entry.value; as value) {\n <span class=\"gbt-chart-legend__value\">{{ value }}</span>\n }\n </li>\n }\n</ul>\n", styles: [".gbt-chart-legend{display:flex;flex-wrap:wrap;gap:.75rem 1.25rem;margin:0;padding:0;list-style:none;font-size:.8125rem;color:var(--text-secondary)}.gbt-chart-legend__item{display:inline-flex;align-items:center;gap:.375rem}.gbt-chart-legend__item:nth-child(3n+1) .gbt-chart-legend__line{stroke:var(--chart-series-1-base)}.gbt-chart-legend__item:nth-child(3n+2) .gbt-chart-legend__line{stroke:var(--chart-series-2-base)}.gbt-chart-legend__item:nth-child(3n+3) .gbt-chart-legend__line{stroke:var(--chart-series-3-base)}.gbt-chart-legend__swatch{width:1.5rem;height:.5rem;flex:none}.gbt-chart-legend__value{margin-left:.375rem;font-variant-numeric:tabular-nums;font-weight:600;color:var(--text-primary)}\n"] }]
1773
- }], propDecorators: { entries: [{ type: i0.Input, args: [{ isSignal: true, alias: "entries", required: true }] }] } });
2047
+ args: [{ selector: 'gbt-chart-legend', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"gbt-chart-legend\">\n @for (entry of entries(); track $index) {\n <li\n class=\"gbt-chart-legend__item\"\n [class.gbt-chart-legend__item--active]=\"interactive() && activeIndex() === $index\"\n [attr.data-pattern]=\"entry.pattern ?? 'solid'\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n (mouseenter)=\"interactive() && activeIndexChange.emit($index)\"\n (mouseleave)=\"interactive() && onMouseLeave($event)\"\n (focus)=\"interactive() && activeIndexChange.emit($index)\"\n (blur)=\"interactive() && activeIndexChange.emit(null)\"\n >\n <svg class=\"gbt-chart-legend__swatch\" viewBox=\"0 0 24 8\" aria-hidden=\"true\" focusable=\"false\">\n @if (entry.color; as color) {\n <rect class=\"gbt-chart-legend__fill\" x=\"4\" y=\"0\" width=\"8\" height=\"8\" rx=\"2\" [attr.fill]=\"color\" />\n } @else {\n <line\n class=\"gbt-chart-legend__line\"\n x1=\"0\"\n y1=\"4\"\n x2=\"24\"\n y2=\"4\"\n [attr.stroke-dasharray]=\"dashArray(entry.pattern)\"\n stroke-width=\"2\"\n />\n }\n </svg>\n {{ entry.label }}\n @if (entry.value; as value) {\n <span class=\"gbt-chart-legend__value\">{{ value }}</span>\n }\n </li>\n }\n</ul>\n", styles: [".gbt-chart-legend{display:flex;flex-wrap:wrap;gap:.75rem 1.25rem;margin:0;padding:0;list-style:none;font-size:.8125rem;color:var(--text-secondary)}.gbt-chart-legend__item{display:inline-flex;align-items:center;gap:.375rem;border-radius:var(--site-border-radius-sm)}.gbt-chart-legend__item:nth-child(3n+1) .gbt-chart-legend__line{stroke:var(--chart-series-1-base)}.gbt-chart-legend__item:nth-child(3n+2) .gbt-chart-legend__line{stroke:var(--chart-series-2-base)}.gbt-chart-legend__item:nth-child(3n+3) .gbt-chart-legend__line{stroke:var(--chart-series-3-base)}.gbt-chart-legend__item[tabindex]{cursor:default;padding:.125rem .25rem;margin:-.125rem -.25rem}.gbt-chart-legend__item[tabindex]:focus-visible{outline:2px solid var(--primary);outline-offset:1px}.gbt-chart-legend__item--active{background:var(--bg-hover)}.gbt-chart-legend__swatch{width:1.5rem;height:.5rem;flex:none}.gbt-chart-legend__value{margin-left:.375rem;font-variant-numeric:tabular-nums;font-weight:600;color:var(--text-primary)}\n"] }]
2048
+ }], propDecorators: { entries: [{ type: i0.Input, args: [{ isSignal: true, alias: "entries", required: true }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], activeIndexChange: [{ type: i0.Output, args: ["activeIndexChange"] }] } });
1774
2049
 
1775
2050
  class ChartEmpty {
1776
2051
  message = input.required(/* @ts-ignore */
@@ -1779,11 +2054,11 @@ class ChartEmpty {
1779
2054
  ...(ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []));
1780
2055
  action = output();
1781
2056
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartEmpty, deps: [], target: i0.ɵɵFactoryTarget.Component });
1782
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ChartEmpty, isStandalone: true, selector: "gbt-chart-empty", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, ngImport: i0, template: "<div class=\"gbt-chart-empty\" role=\"status\">\n <p class=\"gbt-chart-empty__message\">{{ message() }}</p>\n @if (actionLabel()) {\n <button type=\"button\" class=\"gbt-chart-empty__action\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".gbt-chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;min-height:8rem;padding:1.5rem;color:var(--text-secondary);text-align:center}.gbt-chart-empty__message{margin:0;font-size:.875rem}.gbt-chart-empty__action{min-width:24px;min-height:24px;padding:.375rem .75rem;border:1px solid var(--border-color);border-radius:var(--site-border-radius);background:transparent;color:var(--primary);font:inherit;cursor:pointer}.gbt-chart-empty__action:hover{background:var(--bg-hover)}.gbt-chart-empty__action:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2057
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ChartEmpty, isStandalone: true, selector: "gbt-chart-empty", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, ngImport: i0, template: "<div class=\"gbt-chart-empty\" role=\"status\">\n <div class=\"gbt-chart-empty__icon\" aria-hidden=\"true\">\n <ng-content select=\"[gbtChartEmptyIcon]\" />\n </div>\n <p class=\"gbt-chart-empty__message\">{{ message() }}</p>\n @if (actionLabel()) {\n <button type=\"button\" class=\"gbt-chart-empty__action\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".gbt-chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;min-height:8rem;padding:1.5rem;color:var(--text-secondary);text-align:center}.gbt-chart-empty__icon{width:64px;height:64px;color:var(--text-discret)}.gbt-chart-empty__icon:empty{display:none}.gbt-chart-empty__icon svg{width:100%;height:100%}.gbt-chart-empty__message{margin:0;font-size:.875rem}.gbt-chart-empty__action{min-width:24px;min-height:24px;padding:.375rem .75rem;border:1px solid var(--border-color);border-radius:var(--site-border-radius);background:transparent;color:var(--primary);font:inherit;cursor:pointer}.gbt-chart-empty__action:hover{background:var(--bg-hover)}.gbt-chart-empty__action:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1783
2058
  }
1784
2059
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartEmpty, decorators: [{
1785
2060
  type: Component,
1786
- args: [{ selector: 'gbt-chart-empty', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-chart-empty\" role=\"status\">\n <p class=\"gbt-chart-empty__message\">{{ message() }}</p>\n @if (actionLabel()) {\n <button type=\"button\" class=\"gbt-chart-empty__action\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".gbt-chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;min-height:8rem;padding:1.5rem;color:var(--text-secondary);text-align:center}.gbt-chart-empty__message{margin:0;font-size:.875rem}.gbt-chart-empty__action{min-width:24px;min-height:24px;padding:.375rem .75rem;border:1px solid var(--border-color);border-radius:var(--site-border-radius);background:transparent;color:var(--primary);font:inherit;cursor:pointer}.gbt-chart-empty__action:hover{background:var(--bg-hover)}.gbt-chart-empty__action:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"] }]
2061
+ args: [{ selector: 'gbt-chart-empty', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-chart-empty\" role=\"status\">\n <div class=\"gbt-chart-empty__icon\" aria-hidden=\"true\">\n <ng-content select=\"[gbtChartEmptyIcon]\" />\n </div>\n <p class=\"gbt-chart-empty__message\">{{ message() }}</p>\n @if (actionLabel()) {\n <button type=\"button\" class=\"gbt-chart-empty__action\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".gbt-chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;min-height:8rem;padding:1.5rem;color:var(--text-secondary);text-align:center}.gbt-chart-empty__icon{width:64px;height:64px;color:var(--text-discret)}.gbt-chart-empty__icon:empty{display:none}.gbt-chart-empty__icon svg{width:100%;height:100%}.gbt-chart-empty__message{margin:0;font-size:.875rem}.gbt-chart-empty__action{min-width:24px;min-height:24px;padding:.375rem .75rem;border:1px solid var(--border-color);border-radius:var(--site-border-radius);background:transparent;color:var(--primary);font:inherit;cursor:pointer}.gbt-chart-empty__action:hover{background:var(--bg-hover)}.gbt-chart-empty__action:focus-visible{outline:2px solid var(--primary);outline-offset:2px}\n"] }]
1787
2062
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
1788
2063
 
1789
2064
  class ChartTable {
@@ -2042,7 +2317,7 @@ class LineChart {
2042
2317
  }
2043
2318
  }
2044
2319
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: LineChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
2045
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: LineChart, isStandalone: true, selector: "gbt-line-chart", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: true, transformFunction: null }, xKind: { classPropertyName: "xKind", publicName: "xKind", isSignal: true, isRequired: true, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, tableCaption: { classPropertyName: "tableCaption", publicName: "tableCaption", isSignal: true, isRequired: true, transformFunction: null }, xColumn: { classPropertyName: "xColumn", publicName: "xColumn", isSignal: true, isRequired: true, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: true, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, yZero: { classPropertyName: "yZero", publicName: "yZero", isSignal: true, isRequired: false, transformFunction: null }, yTickCount: { classPropertyName: "yTickCount", publicName: "yTickCount", isSignal: true, isRequired: false, transformFunction: null }, xTickCount: { classPropertyName: "xTickCount", publicName: "xTickCount", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, headline: { classPropertyName: "headline", publicName: "headline", isSignal: true, isRequired: false, transformFunction: null }, trend: { classPropertyName: "trend", publicName: "trend", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<gbt-chart-frame\n [label]=\"label()\"\n [x]=\"xSpec()\"\n [y]=\"ySpec()\"\n [pointValues]=\"publicXValues()\"\n [size]=\"size()\"\n [heading]=\"heading()\"\n [headingLevel]=\"headingLevel()\"\n [headline]=\"headline()\"\n [trend]=\"trend()\"\n (activeIndexChange)=\"activeIndex.set($event)\"\n>\n <svg:g gbtChartLayer>\n <svg:g gbtChartAxis axis=\"y\" [locale]=\"locale()\" [tickCount]=\"yTickCount()\" grid></svg:g>\n <svg:g gbtChartAxis axis=\"x\" [locale]=\"locale()\" [tickCount]=\"xTickCount()\"></svg:g>\n <svg:g gbtLineSeries [series]=\"series()\" [area]=\"area()\"></svg:g>\n </svg:g>\n <gbt-chart-tooltip [points]=\"tooltipPoints()\" />\n @if (hasData()) {\n <gbt-chart-table [caption]=\"tableCaption()\" [columns]=\"tableColumns()\" [rows]=\"tableRows()\" />\n } @else {\n <gbt-chart-empty [message]=\"emptyMessage()\" />\n }\n</gbt-chart-frame>\n@if (series().length > 1) {\n <gbt-chart-legend [entries]=\"legendEntries()\" />\n}\n", styles: [":host{display:block;height:100%}gbt-chart-frame{display:block;height:100%}\n"], dependencies: [{ kind: "component", type: ChartFrame, selector: "gbt-chart-frame", inputs: ["label", "heading", "headingLevel", "headline", "trend", "x", "y", "margin", "size", "pointValues"], outputs: ["activeIndexChange"] }, { kind: "component", type: ChartAxis, selector: "g[gbtChartAxis]", inputs: ["axis", "locale", "tickCount", "format", "grid"] }, { kind: "component", type: ChartTooltip, selector: "gbt-chart-tooltip", inputs: ["points"] }, { kind: "component", type: ChartLegend, selector: "gbt-chart-legend", inputs: ["entries"] }, { kind: "component", type: ChartEmpty, selector: "gbt-chart-empty", inputs: ["message", "actionLabel"], outputs: ["action"] }, { kind: "component", type: ChartTable, selector: "gbt-chart-table", inputs: ["caption", "columns", "rows"] }, { kind: "component", type: LineSeries, selector: "g[gbtLineSeries]", inputs: ["series", "area"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2320
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: LineChart, isStandalone: true, selector: "gbt-line-chart", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: true, transformFunction: null }, xKind: { classPropertyName: "xKind", publicName: "xKind", isSignal: true, isRequired: true, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, tableCaption: { classPropertyName: "tableCaption", publicName: "tableCaption", isSignal: true, isRequired: true, transformFunction: null }, xColumn: { classPropertyName: "xColumn", publicName: "xColumn", isSignal: true, isRequired: true, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: true, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, yZero: { classPropertyName: "yZero", publicName: "yZero", isSignal: true, isRequired: false, transformFunction: null }, yTickCount: { classPropertyName: "yTickCount", publicName: "yTickCount", isSignal: true, isRequired: false, transformFunction: null }, xTickCount: { classPropertyName: "xTickCount", publicName: "xTickCount", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, headline: { classPropertyName: "headline", publicName: "headline", isSignal: true, isRequired: false, transformFunction: null }, trend: { classPropertyName: "trend", publicName: "trend", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<gbt-chart-frame\n [label]=\"label()\"\n [x]=\"xSpec()\"\n [y]=\"ySpec()\"\n [pointValues]=\"publicXValues()\"\n [size]=\"size()\"\n [heading]=\"heading()\"\n [headingLevel]=\"headingLevel()\"\n [headline]=\"headline()\"\n [trend]=\"trend()\"\n (activeIndexChange)=\"activeIndex.set($event)\"\n>\n <svg:g gbtChartLayer>\n <svg:g gbtChartAxis axis=\"y\" [locale]=\"locale()\" [tickCount]=\"yTickCount()\" grid></svg:g>\n <svg:g gbtChartAxis axis=\"x\" [locale]=\"locale()\" [tickCount]=\"xTickCount()\"></svg:g>\n <svg:g gbtLineSeries [series]=\"series()\" [area]=\"area()\"></svg:g>\n </svg:g>\n <gbt-chart-tooltip [points]=\"tooltipPoints()\" />\n @if (hasData()) {\n <gbt-chart-table [caption]=\"tableCaption()\" [columns]=\"tableColumns()\" [rows]=\"tableRows()\" />\n } @else {\n <gbt-chart-empty [message]=\"emptyMessage()\" />\n }\n</gbt-chart-frame>\n@if (series().length > 1) {\n <gbt-chart-legend [entries]=\"legendEntries()\" />\n}\n", styles: [":host{display:block;height:100%}gbt-chart-frame{display:block;height:100%}\n"], dependencies: [{ kind: "component", type: ChartFrame, selector: "gbt-chart-frame", inputs: ["label", "heading", "headingLevel", "headline", "trend", "x", "y", "margin", "size", "pointValues"], outputs: ["activeIndexChange"] }, { kind: "component", type: ChartAxis, selector: "g[gbtChartAxis]", inputs: ["axis", "locale", "tickCount", "format", "grid"] }, { kind: "component", type: ChartTooltip, selector: "gbt-chart-tooltip", inputs: ["points"] }, { kind: "component", type: ChartLegend, selector: "gbt-chart-legend", inputs: ["entries", "interactive", "activeIndex"], outputs: ["activeIndexChange"] }, { kind: "component", type: ChartEmpty, selector: "gbt-chart-empty", inputs: ["message", "actionLabel"], outputs: ["action"] }, { kind: "component", type: ChartTable, selector: "gbt-chart-table", inputs: ["caption", "columns", "rows"] }, { kind: "component", type: LineSeries, selector: "g[gbtLineSeries]", inputs: ["series", "area"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2046
2321
  }
2047
2322
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: LineChart, decorators: [{
2048
2323
  type: Component,
@@ -2290,6 +2565,112 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
2290
2565
  args: [{ selector: 'gbt-timeline-chart', standalone: true, imports: [ChartFrame, ChartAxis, ChartTooltip, ChartEmpty, ChartTable, TimelineSeries], changeDetection: ChangeDetectionStrategy.OnPush, template: "<gbt-chart-frame\n [label]=\"label()\"\n [x]=\"xSpec()\"\n [y]=\"ySpec()\"\n [pointValues]=\"publicXValues()\"\n [size]=\"size()\"\n [heading]=\"heading()\"\n [headingLevel]=\"headingLevel()\"\n [headline]=\"headline()\"\n [trend]=\"trend()\"\n>\n <svg:g gbtChartLayer>\n <svg:g gbtChartAxis axis=\"y\" [locale]=\"locale()\" [tickCount]=\"yTickCount()\" grid></svg:g>\n <svg:g gbtChartAxis axis=\"x\" [locale]=\"locale()\"></svg:g>\n <svg:g gbtTimelineSeries [series]=\"series()\" [intervals]=\"intervals()\"></svg:g>\n </svg:g>\n <gbt-chart-tooltip [points]=\"tooltipPoints()\" />\n @if (hasData()) {\n <gbt-chart-table [caption]=\"tableCaption()\" [columns]=\"tableColumns()\" [rows]=\"tableRows()\" />\n }\n @if (hasData() && intervals().length > 0) {\n <gbt-chart-table\n [caption]=\"intervalsCaption()\"\n [columns]=\"intervalColumns()\"\n [rows]=\"intervalRows()\"\n />\n }\n @if (!hasData()) {\n <gbt-chart-empty [message]=\"emptyMessage()\" />\n }\n</gbt-chart-frame>\n", styles: [":host{display:block;height:100%}gbt-chart-frame{display:block;height:100%}\n"] }]
2291
2566
  }], propDecorators: { series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: true }] }], intervals: [{ type: i0.Input, args: [{ isSignal: true, alias: "intervals", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], tableCaption: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableCaption", required: true }] }], intervalsCaption: [{ type: i0.Input, args: [{ isSignal: true, alias: "intervalsCaption", required: true }] }], xColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "xColumn", required: true }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: true }] }], yZero: [{ type: i0.Input, args: [{ isSignal: true, alias: "yZero", required: false }] }], yTickCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "yTickCount", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }], headline: [{ type: i0.Input, args: [{ isSignal: true, alias: "headline", required: false }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }] } });
2292
2567
 
2568
+ const OUTER_RADIUS = 90;
2569
+ const LABEL_RADIUS = OUTER_RADIUS + 14;
2570
+ const LABEL_SHARE_THRESHOLD = 0.15;
2571
+ const PALETTE_SIZE = 6;
2572
+ class PieChart {
2573
+ slices = input.required(/* @ts-ignore */
2574
+ ...(ngDevMode ? [{ debugName: "slices" }] : /* istanbul ignore next */ []));
2575
+ label = input.required(/* @ts-ignore */
2576
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2577
+ locale = input.required(/* @ts-ignore */
2578
+ ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
2579
+ emptyMessage = input.required(/* @ts-ignore */
2580
+ ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
2581
+ tableCaption = input.required(/* @ts-ignore */
2582
+ ...(ngDevMode ? [{ debugName: "tableCaption" }] : /* istanbul ignore next */ []));
2583
+ categoryColumn = input.required(/* @ts-ignore */
2584
+ ...(ngDevMode ? [{ debugName: "categoryColumn" }] : /* istanbul ignore next */ []));
2585
+ valueColumn = input.required(/* @ts-ignore */
2586
+ ...(ngDevMode ? [{ debugName: "valueColumn" }] : /* istanbul ignore next */ []));
2587
+ shareColumn = input.required(/* @ts-ignore */
2588
+ ...(ngDevMode ? [{ debugName: "shareColumn" }] : /* istanbul ignore next */ []));
2589
+ sliceAnnouncement = input.required(/* @ts-ignore */
2590
+ ...(ngDevMode ? [{ debugName: "sliceAnnouncement" }] : /* istanbul ignore next */ []));
2591
+ innerRadiusRatio = input(0, /* @ts-ignore */
2592
+ ...(ngDevMode ? [{ debugName: "innerRadiusRatio" }] : /* istanbul ignore next */ []));
2593
+ activeIndex = signal(null, /* @ts-ignore */
2594
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
2595
+ total = computed(() => this.slices().reduce((sum, slice) => sum + slice.value, 0), /* @ts-ignore */
2596
+ ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
2597
+ renderedSlices = computed(() => {
2598
+ const total = this.total();
2599
+ const innerRadius = OUTER_RADIUS * this.innerRadiusRatio();
2600
+ let angle = 0;
2601
+ return this.slices().map((slice, index) => {
2602
+ const share = total <= 0 ? 0 : slice.value / total;
2603
+ const startAngle = angle;
2604
+ const endAngle = angle + share * Math.PI * 2;
2605
+ angle = endAngle;
2606
+ const midAngle = (startAngle + endAngle) / 2;
2607
+ const labelX = Math.round(LABEL_RADIUS * Math.sin(midAngle) * 100) / 100;
2608
+ const labelY = Math.round(-LABEL_RADIUS * Math.cos(midAngle) * 100) / 100;
2609
+ const formattedValue = formatNumber(slice.value, this.locale());
2610
+ const formattedShare = formatPercent(share, this.locale());
2611
+ return {
2612
+ label: slice.label,
2613
+ formattedValue,
2614
+ formattedShare,
2615
+ path: arcPath({ startAngle, endAngle, innerRadius, outerRadius: OUTER_RADIUS }),
2616
+ color: this.colorFor(index),
2617
+ showLabel: share >= LABEL_SHARE_THRESHOLD,
2618
+ labelX,
2619
+ labelY,
2620
+ labelAnchor: labelX > 5 ? 'start' : labelX < -5 ? 'end' : 'middle',
2621
+ accessibleLabel: `${slice.label} — ${formattedValue}`,
2622
+ };
2623
+ });
2624
+ }, /* @ts-ignore */
2625
+ ...(ngDevMode ? [{ debugName: "renderedSlices" }] : /* istanbul ignore next */ []));
2626
+ legendEntries = computed(() => this.renderedSlices().map((slice) => ({
2627
+ label: slice.label,
2628
+ value: slice.formattedValue,
2629
+ color: slice.color,
2630
+ })), /* @ts-ignore */
2631
+ ...(ngDevMode ? [{ debugName: "legendEntries" }] : /* istanbul ignore next */ []));
2632
+ activeSlice = computed(() => {
2633
+ const index = this.activeIndex();
2634
+ if (index === null)
2635
+ return null;
2636
+ return this.renderedSlices()[index] ?? null;
2637
+ }, /* @ts-ignore */
2638
+ ...(ngDevMode ? [{ debugName: "activeSlice" }] : /* istanbul ignore next */ []));
2639
+ columns = computed(() => [
2640
+ this.categoryColumn(),
2641
+ this.valueColumn(),
2642
+ this.shareColumn(),
2643
+ ], /* @ts-ignore */
2644
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
2645
+ tableRows = computed(() => this.renderedSlices().map((slice) => [slice.label, slice.formattedValue, slice.formattedShare]), /* @ts-ignore */
2646
+ ...(ngDevMode ? [{ debugName: "tableRows" }] : /* istanbul ignore next */ []));
2647
+ colorFor(index) {
2648
+ return `var(--chart-series-${(index % PALETTE_SIZE) + 1}-base)`;
2649
+ }
2650
+ onMouseLeave(event) {
2651
+ const target = event.currentTarget;
2652
+ if (target.ownerDocument.activeElement === target)
2653
+ return;
2654
+ this.activeIndex.set(null);
2655
+ }
2656
+ constructor() {
2657
+ if (isDevMode()) {
2658
+ effect(() => {
2659
+ const count = this.slices().length;
2660
+ if (count > PALETTE_SIZE) {
2661
+ console.warn(`gbt-pie-chart: ${count} slices received for ${PALETTE_SIZE} distinguishable colors. The palette cycles.`);
2662
+ }
2663
+ });
2664
+ }
2665
+ }
2666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: PieChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
2667
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: PieChart, isStandalone: true, selector: "gbt-pie-chart", inputs: { slices: { classPropertyName: "slices", publicName: "slices", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: true, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: true, transformFunction: null }, tableCaption: { classPropertyName: "tableCaption", publicName: "tableCaption", isSignal: true, isRequired: true, transformFunction: null }, categoryColumn: { classPropertyName: "categoryColumn", publicName: "categoryColumn", isSignal: true, isRequired: true, transformFunction: null }, valueColumn: { classPropertyName: "valueColumn", publicName: "valueColumn", isSignal: true, isRequired: true, transformFunction: null }, shareColumn: { classPropertyName: "shareColumn", publicName: "shareColumn", isSignal: true, isRequired: true, transformFunction: null }, sliceAnnouncement: { classPropertyName: "sliceAnnouncement", publicName: "sliceAnnouncement", isSignal: true, isRequired: true, transformFunction: null }, innerRadiusRatio: { classPropertyName: "innerRadiusRatio", publicName: "innerRadiusRatio", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (renderedSlices().length > 0) {\n <div class=\"gbt-pie-chart\">\n <svg class=\"gbt-pie-chart__svg\" viewBox=\"-100 -100 200 200\" role=\"group\" [attr.aria-label]=\"label()\">\n @for (slice of renderedSlices(); track $index) {\n <path\n class=\"gbt-pie-chart__slice\"\n role=\"img\"\n tabindex=\"0\"\n [attr.aria-label]=\"slice.accessibleLabel\"\n [attr.data-active]=\"$index === activeIndex() ? '' : null\"\n [attr.d]=\"slice.path\"\n [attr.fill]=\"slice.color\"\n (mouseenter)=\"activeIndex.set($index)\"\n (mouseleave)=\"onMouseLeave($event)\"\n (focus)=\"activeIndex.set($index)\"\n (blur)=\"activeIndex.set(null)\"\n />\n }\n @for (slice of renderedSlices(); track $index) {\n @if (slice.showLabel) {\n <text\n class=\"gbt-pie-chart__label\"\n aria-hidden=\"true\"\n [attr.x]=\"slice.labelX\"\n [attr.y]=\"slice.labelY\"\n [attr.text-anchor]=\"slice.labelAnchor\"\n >{{ slice.formattedShare }}</text\n >\n }\n }\n </svg>\n <gbt-chart-legend\n [entries]=\"legendEntries()\"\n interactive\n [activeIndex]=\"activeIndex()\"\n (activeIndexChange)=\"activeIndex.set($event)\"\n />\n <div class=\"gbt-sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (activeSlice(); as slice) {\n {{ sliceAnnouncement()(slice.label, slice.formattedValue, slice.formattedShare) }}\n }\n </div>\n <gbt-chart-table [caption]=\"tableCaption()\" [columns]=\"columns()\" [rows]=\"tableRows()\" />\n </div>\n} @else {\n <gbt-chart-empty [message]=\"emptyMessage()\">\n <svg\n gbtChartEmptyIcon\n viewBox=\"0 0 96 96\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"48\" cy=\"48\" r=\"30\" />\n <path d=\"M48 48 L48 18 A30 30 0 0 1 74 63 Z\" fill=\"currentColor\" stroke=\"none\" opacity=\"0.85\" />\n </svg>\n </gbt-chart-empty>\n}\n", styles: [":host{display:block}.gbt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.gbt-pie-chart{display:flex;flex-direction:column;align-items:center;gap:1rem}.gbt-pie-chart__svg{width:100%;max-width:280px;height:auto;overflow:visible}.gbt-pie-chart__slice{stroke:var(--bg-principal);stroke-width:1.5;transition:opacity var(--site-transition-fast)}.gbt-pie-chart__slice:hover,.gbt-pie-chart__slice[data-active]{opacity:.85}.gbt-pie-chart__slice:focus-visible{outline:none;stroke:var(--primary);stroke-width:3}.gbt-pie-chart__label{fill:var(--text-secondary);font-size:9px;font-variant-numeric:tabular-nums;dominant-baseline:middle}\n"], dependencies: [{ kind: "component", type: ChartTable, selector: "gbt-chart-table", inputs: ["caption", "columns", "rows"] }, { kind: "component", type: ChartEmpty, selector: "gbt-chart-empty", inputs: ["message", "actionLabel"], outputs: ["action"] }, { kind: "component", type: ChartLegend, selector: "gbt-chart-legend", inputs: ["entries", "interactive", "activeIndex"], outputs: ["activeIndexChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2668
+ }
2669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: PieChart, decorators: [{
2670
+ type: Component,
2671
+ args: [{ selector: 'gbt-pie-chart', standalone: true, imports: [ChartTable, ChartEmpty, ChartLegend], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (renderedSlices().length > 0) {\n <div class=\"gbt-pie-chart\">\n <svg class=\"gbt-pie-chart__svg\" viewBox=\"-100 -100 200 200\" role=\"group\" [attr.aria-label]=\"label()\">\n @for (slice of renderedSlices(); track $index) {\n <path\n class=\"gbt-pie-chart__slice\"\n role=\"img\"\n tabindex=\"0\"\n [attr.aria-label]=\"slice.accessibleLabel\"\n [attr.data-active]=\"$index === activeIndex() ? '' : null\"\n [attr.d]=\"slice.path\"\n [attr.fill]=\"slice.color\"\n (mouseenter)=\"activeIndex.set($index)\"\n (mouseleave)=\"onMouseLeave($event)\"\n (focus)=\"activeIndex.set($index)\"\n (blur)=\"activeIndex.set(null)\"\n />\n }\n @for (slice of renderedSlices(); track $index) {\n @if (slice.showLabel) {\n <text\n class=\"gbt-pie-chart__label\"\n aria-hidden=\"true\"\n [attr.x]=\"slice.labelX\"\n [attr.y]=\"slice.labelY\"\n [attr.text-anchor]=\"slice.labelAnchor\"\n >{{ slice.formattedShare }}</text\n >\n }\n }\n </svg>\n <gbt-chart-legend\n [entries]=\"legendEntries()\"\n interactive\n [activeIndex]=\"activeIndex()\"\n (activeIndexChange)=\"activeIndex.set($event)\"\n />\n <div class=\"gbt-sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (activeSlice(); as slice) {\n {{ sliceAnnouncement()(slice.label, slice.formattedValue, slice.formattedShare) }}\n }\n </div>\n <gbt-chart-table [caption]=\"tableCaption()\" [columns]=\"columns()\" [rows]=\"tableRows()\" />\n </div>\n} @else {\n <gbt-chart-empty [message]=\"emptyMessage()\">\n <svg\n gbtChartEmptyIcon\n viewBox=\"0 0 96 96\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"48\" cy=\"48\" r=\"30\" />\n <path d=\"M48 48 L48 18 A30 30 0 0 1 74 63 Z\" fill=\"currentColor\" stroke=\"none\" opacity=\"0.85\" />\n </svg>\n </gbt-chart-empty>\n}\n", styles: [":host{display:block}.gbt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.gbt-pie-chart{display:flex;flex-direction:column;align-items:center;gap:1rem}.gbt-pie-chart__svg{width:100%;max-width:280px;height:auto;overflow:visible}.gbt-pie-chart__slice{stroke:var(--bg-principal);stroke-width:1.5;transition:opacity var(--site-transition-fast)}.gbt-pie-chart__slice:hover,.gbt-pie-chart__slice[data-active]{opacity:.85}.gbt-pie-chart__slice:focus-visible{outline:none;stroke:var(--primary);stroke-width:3}.gbt-pie-chart__label{fill:var(--text-secondary);font-size:9px;font-variant-numeric:tabular-nums;dominant-baseline:middle}\n"] }]
2672
+ }], ctorParameters: () => [], propDecorators: { slices: [{ type: i0.Input, args: [{ isSignal: true, alias: "slices", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: true }] }], tableCaption: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableCaption", required: true }] }], categoryColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoryColumn", required: true }] }], valueColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueColumn", required: true }] }], shareColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "shareColumn", required: true }] }], sliceAnnouncement: [{ type: i0.Input, args: [{ isSignal: true, alias: "sliceAnnouncement", required: true }] }], innerRadiusRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadiusRatio", required: false }] }] } });
2673
+
2293
2674
  const MARGIN = 4;
2294
2675
  class Sparkline {
2295
2676
  values = input.required(/* @ts-ignore */
@@ -2695,253 +3076,1282 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
2695
3076
  }, 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"] }]
2696
3077
  }], 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 }] }] } });
2697
3078
 
2698
- const ELLIPSIS = '…';
2699
- function range(start, end) {
2700
- return Array.from({ length: end - start + 1 }, (_, i) => start + i);
2701
- }
2702
- function paginationRange(page, pageCount, siblingCount) {
2703
- const totalPageNumbers = siblingCount + 5;
2704
- if (totalPageNumbers >= pageCount) {
2705
- return range(1, pageCount);
3079
+ let nextPopoverId = 0;
3080
+ class Popover {
3081
+ elementRef = inject((ElementRef));
3082
+ triggerSlot = viewChild('triggerSlot', /* @ts-ignore */
3083
+ ...(ngDevMode ? [{ debugName: "triggerSlot" }] : /* istanbul ignore next */ []));
3084
+ align = input('start', /* @ts-ignore */
3085
+ ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
3086
+ panelId = `gbt-popover-${++nextPopoverId}`;
3087
+ isOpen = signal(false, /* @ts-ignore */
3088
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
3089
+ open = this.isOpen.asReadonly();
3090
+ position = signal(null, /* @ts-ignore */
3091
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
3092
+ toggle() {
3093
+ this.isOpen.update((value) => !value);
3094
+ if (this.isOpen()) {
3095
+ this.updatePosition();
3096
+ }
2706
3097
  }
2707
- const leftSiblingIndex = Math.max(page - siblingCount, 1);
2708
- const rightSiblingIndex = Math.min(page + siblingCount, pageCount);
2709
- const shouldShowLeftDots = leftSiblingIndex > 2;
2710
- // -2, not -1: a lone skipped page right before the last one isn't worth an
2711
- // ellipsis — showing that page costs no more room than the "…" would.
2712
- const shouldShowRightDots = rightSiblingIndex < pageCount - 2;
2713
- if (!shouldShowLeftDots && shouldShowRightDots) {
2714
- const leftItemCount = 3 + siblingCount * 2;
2715
- return [...range(1, leftItemCount), ELLIPSIS, pageCount];
3098
+ close(returnFocus = false) {
3099
+ if (!this.isOpen()) {
3100
+ return;
3101
+ }
3102
+ this.isOpen.set(false);
3103
+ if (returnFocus) {
3104
+ this.focusTrigger();
3105
+ }
2716
3106
  }
2717
- if (shouldShowLeftDots && !shouldShowRightDots) {
2718
- const rightItemCount = 3 + siblingCount * 2;
2719
- return [1, ELLIPSIS, ...range(pageCount - rightItemCount + 1, pageCount)];
3107
+ onTriggerClick(event) {
3108
+ const trigger = this.triggerSlot()?.nativeElement;
3109
+ if (trigger?.contains(event.target)) {
3110
+ this.toggle();
3111
+ }
2720
3112
  }
2721
- return [1, ELLIPSIS, ...range(leftSiblingIndex, rightSiblingIndex), ELLIPSIS, pageCount];
3113
+ updatePosition() {
3114
+ if (!this.isOpen()) {
3115
+ return;
3116
+ }
3117
+ const trigger = this.triggerSlot()?.nativeElement;
3118
+ if (!trigger) {
3119
+ return;
3120
+ }
3121
+ const rect = trigger.getBoundingClientRect();
3122
+ this.position.set(this.align() === 'end'
3123
+ ? { top: `${rect.bottom + 6}px`, left: null, right: `${window.innerWidth - rect.right}px` }
3124
+ : { top: `${rect.bottom + 6}px`, left: `${rect.left}px`, right: null });
3125
+ }
3126
+ handleClickOutside(event) {
3127
+ if (this.isOpen() && !this.elementRef.nativeElement.contains(event.target)) {
3128
+ this.close(false);
3129
+ }
3130
+ }
3131
+ onKeydown(event) {
3132
+ if (event.key === 'Escape' && this.isOpen()) {
3133
+ event.preventDefault();
3134
+ event.stopPropagation();
3135
+ this.close(true);
3136
+ }
3137
+ }
3138
+ focusTrigger() {
3139
+ const trigger = this.triggerSlot()?.nativeElement;
3140
+ trigger?.querySelector('button, a[href], input, select, textarea, [tabindex]')?.focus();
3141
+ }
3142
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Popover, deps: [], target: i0.ɵɵFactoryTarget.Component });
3143
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Popover, isStandalone: true, selector: "gbt-popover", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onTriggerClick($event)", "document:click": "handleClickOutside($event)", "keydown": "onKeydown($event)", "window:scroll": "updatePosition()", "window:resize": "updatePosition()" }, classAttribute: "gbt-popover-host" }, viewQueries: [{ propertyName: "triggerSlot", first: true, predicate: ["triggerSlot"], descendants: true, isSignal: true }], exportAs: ["gbtPopover"], ngImport: i0, template: "<span #triggerSlot class=\"gbt-popover__trigger\">\n <ng-content></ng-content>\n</span>\n@if (open() && position(); as pos) {\n <div class=\"gbt-popover__panel\" [id]=\"panelId\" [style.top]=\"pos.top\" [style.left]=\"pos.left\" [style.right]=\"pos.right\">\n <ng-content select=\"[popover-content]\"></ng-content>\n </div>\n}\n", styles: [":host{position:relative;display:inline-block}.gbt-popover__trigger{display:inline-block;cursor:pointer}.gbt-popover__panel{box-sizing:border-box;position:fixed;z-index:1000;min-width:200px;padding:1rem;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-lg);color:var(--text-primary);animation:gbt-popover-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-popover-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-popover__panel{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2722
3144
  }
2723
- class Pagination {
2724
- page = input(1, /* @ts-ignore */
2725
- ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
2726
- pageSize = input(10, /* @ts-ignore */
2727
- ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
2728
- totalItems = input.required(/* @ts-ignore */
2729
- ...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
2730
- siblingCount = input(1, /* @ts-ignore */
2731
- ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
2732
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2733
- ariaLabel = input('Pagination', /* @ts-ignore */
3145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Popover, decorators: [{
3146
+ type: Component,
3147
+ args: [{ selector: 'gbt-popover', standalone: true, exportAs: 'gbtPopover', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3148
+ class: 'gbt-popover-host',
3149
+ '(click)': 'onTriggerClick($event)',
3150
+ '(document:click)': 'handleClickOutside($event)',
3151
+ '(keydown)': 'onKeydown($event)',
3152
+ '(window:scroll)': 'updatePosition()',
3153
+ '(window:resize)': 'updatePosition()',
3154
+ }, template: "<span #triggerSlot class=\"gbt-popover__trigger\">\n <ng-content></ng-content>\n</span>\n@if (open() && position(); as pos) {\n <div class=\"gbt-popover__panel\" [id]=\"panelId\" [style.top]=\"pos.top\" [style.left]=\"pos.left\" [style.right]=\"pos.right\">\n <ng-content select=\"[popover-content]\"></ng-content>\n </div>\n}\n", styles: [":host{position:relative;display:inline-block}.gbt-popover__trigger{display:inline-block;cursor:pointer}.gbt-popover__panel{box-sizing:border-box;position:fixed;z-index:1000;min-width:200px;padding:1rem;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-lg);color:var(--text-primary);animation:gbt-popover-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}@keyframes gbt-popover-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-reduced-motion:reduce){.gbt-popover__panel{animation:none}}\n"] }]
3155
+ }], propDecorators: { triggerSlot: [{ type: i0.ViewChild, args: ['triggerSlot', { isSignal: true }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }] } });
3156
+
3157
+ class DescriptionList {
3158
+ items = input.required(/* @ts-ignore */
3159
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
3160
+ layout = input('stacked', /* @ts-ignore */
3161
+ ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
3162
+ isTemplate(value) {
3163
+ return value instanceof TemplateRef;
3164
+ }
3165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DescriptionList, deps: [], target: i0.ɵɵFactoryTarget.Component });
3166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: DescriptionList, isStandalone: true, selector: "gbt-description-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<dl class=\"gbt-description-list\" [attr.data-layout]=\"layout()\">\n @for (item of items(); track $index) {\n <dt class=\"gbt-description-list__term\">{{ item.term }}</dt>\n <dd class=\"gbt-description-list__value\">\n @if (isTemplate(item.value)) {\n <ng-container [ngTemplateOutlet]=\"item.value\"></ng-container>\n } @else {\n {{ item.value }}\n }\n </dd>\n }\n</dl>\n", styles: [".gbt-description-list{margin:0}.gbt-description-list[data-layout=stacked]{display:block}.gbt-description-list[data-layout=inline]{display:grid;grid-template-columns:max-content 1fr;column-gap:1rem;row-gap:.5rem;align-items:baseline}@media(max-width:768px){.gbt-description-list[data-layout=inline]{display:block}}.gbt-description-list__term{margin:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-description-list__value{margin:0 0 1rem;color:var(--text-primary);font-size:.875rem}.gbt-description-list[data-layout=inline] .gbt-description-list__value{margin-bottom:0}@media(max-width:768px){.gbt-description-list[data-layout=inline] .gbt-description-list__value{margin-bottom:1rem}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3167
+ }
3168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DescriptionList, decorators: [{
3169
+ type: Component,
3170
+ args: [{ selector: 'gbt-description-list', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<dl class=\"gbt-description-list\" [attr.data-layout]=\"layout()\">\n @for (item of items(); track $index) {\n <dt class=\"gbt-description-list__term\">{{ item.term }}</dt>\n <dd class=\"gbt-description-list__value\">\n @if (isTemplate(item.value)) {\n <ng-container [ngTemplateOutlet]=\"item.value\"></ng-container>\n } @else {\n {{ item.value }}\n }\n </dd>\n }\n</dl>\n", styles: [".gbt-description-list{margin:0}.gbt-description-list[data-layout=stacked]{display:block}.gbt-description-list[data-layout=inline]{display:grid;grid-template-columns:max-content 1fr;column-gap:1rem;row-gap:.5rem;align-items:baseline}@media(max-width:768px){.gbt-description-list[data-layout=inline]{display:block}}.gbt-description-list__term{margin:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-description-list__value{margin:0 0 1rem;color:var(--text-primary);font-size:.875rem}.gbt-description-list[data-layout=inline] .gbt-description-list__value{margin-bottom:0}@media(max-width:768px){.gbt-description-list[data-layout=inline] .gbt-description-list__value{margin-bottom:1rem}}\n"] }]
3171
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
3172
+
3173
+ class SegmentedControl {
3174
+ group = viewChild('group', /* @ts-ignore */
3175
+ ...(ngDevMode ? [{ debugName: "group" }] : /* istanbul ignore next */ []));
3176
+ options = input.required(/* @ts-ignore */
3177
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3178
+ value = model.required(/* @ts-ignore */
3179
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3180
+ ariaLabel = input('', /* @ts-ignore */
2734
3181
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2735
- previousLabel = input('Previous page', /* @ts-ignore */
2736
- ...(ngDevMode ? [{ debugName: "previousLabel" }] : /* istanbul ignore next */ []));
2737
- nextLabel = input('Next page', /* @ts-ignore */
2738
- ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
2739
- pageLabel = input((page) => `Page ${page}`, /* @ts-ignore */
2740
- ...(ngDevMode ? [{ debugName: "pageLabel" }] : /* istanbul ignore next */ []));
2741
- pageSizeOptions = input([], /* @ts-ignore */
2742
- ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
2743
- pageSizeLabel = input((size) => `${size} / page`, /* @ts-ignore */
2744
- ...(ngDevMode ? [{ debugName: "pageSizeLabel" }] : /* istanbul ignore next */ []));
2745
- pageSizeSelectLabel = input('Rows per page', /* @ts-ignore */
2746
- ...(ngDevMode ? [{ debugName: "pageSizeSelectLabel" }] : /* istanbul ignore next */ []));
2747
- showItemsSummary = input(false, { ...(ngDevMode ? { debugName: "showItemsSummary" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2748
- itemsSummaryLabel = input((shown, total) => `${shown} of ${total} items`, /* @ts-ignore */
2749
- ...(ngDevMode ? [{ debugName: "itemsSummaryLabel" }] : /* istanbul ignore next */ []));
2750
- pageChange = output();
2751
- pageSizeChange = output();
2752
- ELLIPSIS = ELLIPSIS;
2753
- pageCount = computed(() => Math.max(1, Math.ceil(this.totalItems() / this.pageSize())), /* @ts-ignore */
2754
- ...(ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []));
2755
- items = computed(() => paginationRange(this.page(), this.pageCount(), this.siblingCount()), /* @ts-ignore */
2756
- ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
2757
- itemsShown = computed(() => {
2758
- const start = (this.page() - 1) * this.pageSize();
2759
- return Math.max(0, Math.min(this.pageSize(), this.totalItems() - start));
2760
- }, /* @ts-ignore */
2761
- ...(ngDevMode ? [{ debugName: "itemsShown" }] : /* istanbul ignore next */ []));
2762
- itemsSummary = computed(() => this.itemsSummaryLabel()(this.itemsShown(), this.totalItems()), /* @ts-ignore */
2763
- ...(ngDevMode ? [{ debugName: "itemsSummary" }] : /* istanbul ignore next */ []));
2764
- pageSizeSelectOptions = computed(() => this.pageSizeOptions().map((size) => ({ value: size, label: this.pageSizeLabel()(size) })), /* @ts-ignore */
2765
- ...(ngDevMode ? [{ debugName: "pageSizeSelectOptions" }] : /* istanbul ignore next */ []));
2766
- pageSizeControl = new FormControl(this.pageSize(), {
2767
- nonNullable: true,
2768
- });
2769
- constructor() {
2770
- effect(() => {
2771
- const size = this.pageSize();
2772
- if (this.pageSizeControl.value !== size) {
2773
- this.pageSizeControl.setValue(size, { emitEvent: false });
2774
- }
2775
- });
2776
- this.pageSizeControl.valueChanges.pipe(takeUntilDestroyed()).subscribe((size) => {
2777
- this.pageSizeChange.emit(size);
2778
- this.pageChange.emit(1);
2779
- });
2780
- // Self-heals a stale `page` — e.g. a filter shrinks `totalItems` while
2781
- // the app was sitting on a now out-of-range page — instead of leaving
2782
- // the pager stuck with no page marked current and a live "previous"
2783
- // button pointing at a page that no longer exists.
2784
- effect(() => {
2785
- const count = this.pageCount();
2786
- const current = this.page();
2787
- const clamped = Math.min(Math.max(current, 1), count);
2788
- if (clamped !== current) {
2789
- this.pageChange.emit(clamped);
2790
- }
2791
- });
3182
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3183
+ isSelected(value) {
3184
+ return this.value() === value;
2792
3185
  }
2793
- goTo(page) {
2794
- if (this.disabled())
3186
+ select(option) {
3187
+ if (this.disabled() || option.disabled) {
2795
3188
  return;
2796
- const clamped = Math.min(Math.max(page, 1), this.pageCount());
2797
- if (clamped === this.page())
3189
+ }
3190
+ this.value.set(option.value);
3191
+ }
3192
+ onKeydown(event, index) {
3193
+ const options = this.options();
3194
+ const count = options.length;
3195
+ if (count === 0) {
2798
3196
  return;
2799
- this.pageChange.emit(clamped);
3197
+ }
3198
+ let next = null;
3199
+ switch (event.key) {
3200
+ case 'ArrowRight':
3201
+ case 'ArrowDown':
3202
+ next = this.nextEnabledIndex(index, 1);
3203
+ break;
3204
+ case 'ArrowLeft':
3205
+ case 'ArrowUp':
3206
+ next = this.nextEnabledIndex(index, -1);
3207
+ break;
3208
+ case 'Home':
3209
+ next = this.nextEnabledIndex(-1, 1);
3210
+ break;
3211
+ case 'End':
3212
+ next = this.nextEnabledIndex(count, -1);
3213
+ break;
3214
+ }
3215
+ if (next === null) {
3216
+ return;
3217
+ }
3218
+ event.preventDefault();
3219
+ this.select(options[next]);
3220
+ this.focusButton(next);
2800
3221
  }
2801
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Pagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
2802
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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", "chips", "placeholder", "disabled", "required", "errorMessage", "selectedCountLabel", "chipRemoveLabel"] }, { 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 });
3222
+ nextEnabledIndex(from, direction) {
3223
+ const options = this.options();
3224
+ const count = options.length;
3225
+ for (let step = 1; step <= count; step++) {
3226
+ const candidate = (from + direction * step + count) % count;
3227
+ if (!options[candidate].disabled) {
3228
+ return candidate;
3229
+ }
3230
+ }
3231
+ return null;
3232
+ }
3233
+ focusButton(index) {
3234
+ this.group()?.nativeElement.querySelectorAll('[role="radio"]')[index]?.focus();
3235
+ }
3236
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SegmentedControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
3237
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: SegmentedControl, isStandalone: true, selector: "gbt-segmented-control", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, viewQueries: [{ propertyName: "group", first: true, predicate: ["group"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #group class=\"gbt-segmented-control\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel() || null\">\n @for (option of options(); track option.value; let i = $index) {\n <button\n type=\"button\"\n role=\"radio\"\n class=\"gbt-segmented-control__option\"\n [class.gbt-segmented-control__option--selected]=\"isSelected(option.value)\"\n [attr.aria-checked]=\"isSelected(option.value)\"\n [tabIndex]=\"isSelected(option.value) ? 0 : -1\"\n [disabled]=\"disabled() || !!option.disabled\"\n (click)=\"select(option)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n {{ option.label }}\n </button>\n }\n</div>\n", styles: [".gbt-segmented-control{display:inline-flex;gap:2px;padding:2px;background:var(--bg-panel);border-radius:var(--site-border-radius-sm)}.gbt-segmented-control__option{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;padding:.375rem .75rem;background:none;border:none;border-radius:calc(var(--site-border-radius-sm) - 2px);color:var(--text-secondary);font-size:13px;font-weight:600;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1),color .12s cubic-bezier(.4,0,.2,1)}.gbt-segmented-control__option:hover:not(:disabled):not(.gbt-segmented-control__option--selected){color:var(--text-primary)}.gbt-segmented-control__option:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-segmented-control__option:disabled{cursor:not-allowed;opacity:.5}.gbt-segmented-control__option--selected{background:var(--bg-principal);color:var(--text-primary);box-shadow:var(--site-shadow-sm)}@media(prefers-reduced-motion:reduce){.gbt-segmented-control__option{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2803
3238
  }
2804
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Pagination, decorators: [{
3239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SegmentedControl, decorators: [{
2805
3240
  type: Component,
2806
- 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"] }]
2807
- }], 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"] }] } });
3241
+ args: [{ selector: 'gbt-segmented-control', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #group class=\"gbt-segmented-control\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel() || null\">\n @for (option of options(); track option.value; let i = $index) {\n <button\n type=\"button\"\n role=\"radio\"\n class=\"gbt-segmented-control__option\"\n [class.gbt-segmented-control__option--selected]=\"isSelected(option.value)\"\n [attr.aria-checked]=\"isSelected(option.value)\"\n [tabIndex]=\"isSelected(option.value) ? 0 : -1\"\n [disabled]=\"disabled() || !!option.disabled\"\n (click)=\"select(option)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n {{ option.label }}\n </button>\n }\n</div>\n", styles: [".gbt-segmented-control{display:inline-flex;gap:2px;padding:2px;background:var(--bg-panel);border-radius:var(--site-border-radius-sm)}.gbt-segmented-control__option{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;padding:.375rem .75rem;background:none;border:none;border-radius:calc(var(--site-border-radius-sm) - 2px);color:var(--text-secondary);font-size:13px;font-weight:600;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1),color .12s cubic-bezier(.4,0,.2,1)}.gbt-segmented-control__option:hover:not(:disabled):not(.gbt-segmented-control__option--selected){color:var(--text-primary)}.gbt-segmented-control__option:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-segmented-control__option:disabled{cursor:not-allowed;opacity:.5}.gbt-segmented-control__option--selected{background:var(--bg-principal);color:var(--text-primary);box-shadow:var(--site-shadow-sm)}@media(prefers-reduced-motion:reduce){.gbt-segmented-control__option{transition:none}}\n"] }]
3242
+ }], propDecorators: { group: [{ type: i0.ViewChild, args: ['group', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }, { type: i0.Output, args: ["valueChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
2808
3243
 
2809
- class Breadcrumb {
2810
- ariaLabel = input.required(/* @ts-ignore */
2811
- ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2812
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Breadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
2813
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", 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 });
3244
+ function isSameDay(a, b) {
3245
+ return (a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate());
2814
3246
  }
2815
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Breadcrumb, decorators: [{
2816
- type: Component,
2817
- 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"] }]
2818
- }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }] } });
2819
-
2820
- class ConfirmDangerModal {
2821
- isOpen = input.required(/* @ts-ignore */
2822
- ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
2823
- heading = input.required(/* @ts-ignore */
2824
- ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
2825
- message = input.required(/* @ts-ignore */
2826
- ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
2827
- confirmText = input.required(/* @ts-ignore */
2828
- ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
2829
- confirmInputLabel = input('Type to confirm', /* @ts-ignore */
2830
- ...(ngDevMode ? [{ debugName: "confirmInputLabel" }] : /* istanbul ignore next */ []));
2831
- confirmLabel = input('Confirm', /* @ts-ignore */
2832
- ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
2833
- cancelLabel = input('Cancel', /* @ts-ignore */
2834
- ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
2835
- closeLabel = input('Close', /* @ts-ignore */
2836
- ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
2837
- confirmed = output();
2838
- closed = output();
2839
- typed = signal('', /* @ts-ignore */
2840
- ...(ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []));
2841
- canConfirm = computed(() => this.typed().length > 0 && this.typed() === this.confirmText(), /* @ts-ignore */
2842
- ...(ngDevMode ? [{ debugName: "canConfirm" }] : /* istanbul ignore next */ []));
2843
- constructor() {
2844
- // Cleared whenever the modal transitions to closed (Cancel, Escape,
2845
- // backdrop, or the consumer setting isOpen false after a successful
2846
- // confirm) — a later reopen must never show the previous attempt's text.
2847
- effect(() => {
2848
- if (!this.isOpen()) {
2849
- this.typed.set('');
2850
- }
3247
+ /** Adds `delta` whole months, clamping an overflowing day to the target month's last day. */
3248
+ function addMonths(date, delta) {
3249
+ const day = date.getDate();
3250
+ const firstOfTarget = new Date(date.getFullYear(), date.getMonth() + delta, 1);
3251
+ const daysInTarget = new Date(firstOfTarget.getFullYear(), firstOfTarget.getMonth() + 1, 0).getDate();
3252
+ return new Date(firstOfTarget.getFullYear(), firstOfTarget.getMonth(), Math.min(day, daysInTarget));
3253
+ }
3254
+ /** Adds `delta` whole years, clamping Feb 29 to Feb 28 on a non-leap target year. */
3255
+ function addYears(date, delta) {
3256
+ return addMonths(date, delta * 12);
3257
+ }
3258
+ function startOfWeek(date, weekStartsOn) {
3259
+ const weekday = date.getDay();
3260
+ const diff = (weekday - weekStartsOn + 7) % 7;
3261
+ const result = new Date(date.getFullYear(), date.getMonth(), date.getDate());
3262
+ result.setDate(result.getDate() - diff);
3263
+ return result;
3264
+ }
3265
+ function endOfWeek(date, weekStartsOn) {
3266
+ const start = startOfWeek(date, weekStartsOn);
3267
+ start.setDate(start.getDate() + 6);
3268
+ return start;
3269
+ }
3270
+ /** Always 42 days (6 full weeks), starting on the week containing the 1st of `month`. */
3271
+ function buildCalendarGrid(year, month, weekStartsOn) {
3272
+ const firstOfMonth = new Date(year, month, 1);
3273
+ const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
3274
+ const today = new Date();
3275
+ const days = [];
3276
+ for (let i = 0; i < 42; i++) {
3277
+ const date = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);
3278
+ days.push({
3279
+ date,
3280
+ inCurrentMonth: date.getMonth() === month,
3281
+ isToday: isSameDay(date, today),
2851
3282
  });
2852
3283
  }
2853
- confirm() {
2854
- if (this.canConfirm()) {
2855
- this.confirmed.emit();
2856
- }
2857
- }
2858
- cancel() {
2859
- this.closed.emit();
2860
- }
2861
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ConfirmDangerModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
2862
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", 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 });
3284
+ return days;
3285
+ }
3286
+ function weekdayLabels(locale, weekStartsOn) {
3287
+ const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short' });
3288
+ // Any Sunday-anchored reference week: Jan 7 2024 is a Sunday.
3289
+ const reference = new Date(2024, 0, 7 + weekStartsOn);
3290
+ return Array.from({ length: 7 }, (_, i) => {
3291
+ const date = new Date(reference.getFullYear(), reference.getMonth(), reference.getDate() + i);
3292
+ return formatter.format(date);
3293
+ });
2863
3294
  }
2864
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ConfirmDangerModal, decorators: [{
2865
- type: Component,
2866
- 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"] }]
2867
- }], 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"] }] } });
2868
3295
 
2869
- const DEFAULT_DURATION_MS = 5000;
2870
- const ASSERTIVE_VARIANTS = new Set(['warning', 'error']);
2871
- const VARIANT_ICONS = {
2872
- success: 'check-circle',
2873
- error: 'alert-circle',
2874
- warning: 'alert-triangle',
2875
- info: 'info',
2876
- };
2877
- class Toaster {
2878
- toasts = input.required(/* @ts-ignore */
2879
- ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
2880
- position = input('bottom-right', /* @ts-ignore */
2881
- ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
2882
- closeLabel = input('Close', /* @ts-ignore */
2883
- ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
2884
- dismissed = output();
2885
- timers = new Map();
2886
- constructor() {
2887
- effect(() => {
2888
- const currentIds = new Set(this.toasts().map((toast) => toast.id));
2889
- for (const [id, timer] of this.timers) {
2890
- if (!currentIds.has(id)) {
2891
- clearTimeout(timer);
2892
- this.timers.delete(id);
2893
- }
3296
+ let nextDatePickerId = 0;
3297
+ const CURRENT_YEAR$1 = new Date().getFullYear();
3298
+ class DatePicker {
3299
+ elementRef = inject(ElementRef);
3300
+ injector = inject(Injector);
3301
+ id = input(`gbt-date-picker-${++nextDatePickerId}`, /* @ts-ignore */
3302
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3303
+ label = input('', /* @ts-ignore */
3304
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3305
+ placeholder = input('Select a date…', /* @ts-ignore */
3306
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3307
+ locale = input('en-US', /* @ts-ignore */
3308
+ ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
3309
+ weekStartsOn = input(1, /* @ts-ignore */
3310
+ ...(ngDevMode ? [{ debugName: "weekStartsOn" }] : /* istanbul ignore next */ []));
3311
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3312
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3313
+ errorMessage = input(null, /* @ts-ignore */
3314
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3315
+ previousMonthLabel = input('Previous month', /* @ts-ignore */
3316
+ ...(ngDevMode ? [{ debugName: "previousMonthLabel" }] : /* istanbul ignore next */ []));
3317
+ nextMonthLabel = input('Next month', /* @ts-ignore */
3318
+ ...(ngDevMode ? [{ debugName: "nextMonthLabel" }] : /* istanbul ignore next */ []));
3319
+ clearable = input(false, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3320
+ clearLabel = input('Clear date', /* @ts-ignore */
3321
+ ...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
3322
+ visibleMonths = input(1, /* @ts-ignore */
3323
+ ...(ngDevMode ? [{ debugName: "visibleMonths" }] : /* istanbul ignore next */ []));
3324
+ monthSelectLabel = input('Month', /* @ts-ignore */
3325
+ ...(ngDevMode ? [{ debugName: "monthSelectLabel" }] : /* istanbul ignore next */ []));
3326
+ yearSelectLabel = input('Year', /* @ts-ignore */
3327
+ ...(ngDevMode ? [{ debugName: "yearSelectLabel" }] : /* istanbul ignore next */ []));
3328
+ minYear = input(CURRENT_YEAR$1 - 100, /* @ts-ignore */
3329
+ ...(ngDevMode ? [{ debugName: "minYear" }] : /* istanbul ignore next */ []));
3330
+ maxYear = input(CURRENT_YEAR$1 + 10, /* @ts-ignore */
3331
+ ...(ngDevMode ? [{ debugName: "maxYear" }] : /* istanbul ignore next */ []));
3332
+ open = signal(false, /* @ts-ignore */
3333
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
3334
+ selected = signal(null, /* @ts-ignore */
3335
+ ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
3336
+ focusedDate = signal(new Date(), /* @ts-ignore */
3337
+ ...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
3338
+ anchorDate = signal(new Date(), /* @ts-ignore */
3339
+ ...(ngDevMode ? [{ debugName: "anchorDate" }] : /* istanbul ignore next */ []));
3340
+ panelStyle = signal(null, /* @ts-ignore */
3341
+ ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
3342
+ formDisabled = signal(false, /* @ts-ignore */
3343
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3344
+ onChange = () => { };
3345
+ onTouched = () => { };
3346
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3347
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
3348
+ showClear = computed(() => this.clearable() && this.selected() !== null && !this.isDisabled(), /* @ts-ignore */
3349
+ ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
3350
+ monthViews = computed(() => {
3351
+ const anchor = this.anchorDate();
3352
+ const count = this.visibleMonths();
3353
+ const formatter = new Intl.DateTimeFormat(this.locale(), { month: 'long', year: 'numeric' });
3354
+ const views = Array.from({ length: count }, (_, i) => {
3355
+ const monthDate = new Date(anchor.getFullYear(), anchor.getMonth() + i, 1);
3356
+ const year = monthDate.getFullYear();
3357
+ const month = monthDate.getMonth();
3358
+ const days = buildCalendarGrid(year, month, this.weekStartsOn());
3359
+ const weeks = [];
3360
+ for (let d = 0; d < days.length; d += 7) {
3361
+ weeks.push(days.slice(d, d + 7));
2894
3362
  }
2895
- for (const toast of this.toasts()) {
2896
- if (this.timers.has(toast.id)) {
2897
- continue;
2898
- }
2899
- const duration = toast.duration ?? DEFAULT_DURATION_MS;
2900
- if (!Number.isFinite(duration) || duration <= 0) {
2901
- continue;
2902
- }
2903
- this.timers.set(toast.id, setTimeout(() => {
2904
- this.timers.delete(toast.id);
2905
- this.dismissed.emit(toast.id);
2906
- }, duration));
3363
+ return { year, month, label: formatter.format(monthDate), weeks };
3364
+ });
3365
+ // Trim wholly-blank trailing weeks (pure next-month filler) — but by the
3366
+ // same amount across every visible month, so side-by-side calendars
3367
+ // (`visibleMonths="2"`) stay the same height even when only one of them
3368
+ // actually needs the extra week.
3369
+ const neededWeeks = views.map((view) => {
3370
+ let last = view.weeks.length;
3371
+ while (last > 1 && view.weeks[last - 1].every((day) => !day.inCurrentMonth)) {
3372
+ last--;
2907
3373
  }
3374
+ return last;
2908
3375
  });
2909
- }
2910
- ngOnDestroy() {
2911
- for (const timer of this.timers.values()) {
2912
- clearTimeout(timer);
3376
+ const sharedWeeks = Math.max(...neededWeeks);
3377
+ return views.map((view) => ({ ...view, weeks: view.weeks.slice(0, sharedWeeks) }));
3378
+ }, /* @ts-ignore */
3379
+ ...(ngDevMode ? [{ debugName: "monthViews" }] : /* istanbul ignore next */ []));
3380
+ panelLabel = computed(() => {
3381
+ const views = this.monthViews();
3382
+ return views.length === 1 ? views[0].label : `${views[0].label} – ${views[views.length - 1].label}`;
3383
+ }, /* @ts-ignore */
3384
+ ...(ngDevMode ? [{ debugName: "panelLabel" }] : /* istanbul ignore next */ []));
3385
+ weekdayLabels = computed(() => weekdayLabels(this.locale(), this.weekStartsOn()), /* @ts-ignore */
3386
+ ...(ngDevMode ? [{ debugName: "weekdayLabels" }] : /* istanbul ignore next */ []));
3387
+ monthOptions = computed(() => {
3388
+ const formatter = new Intl.DateTimeFormat(this.locale(), { month: 'long' });
3389
+ return Array.from({ length: 12 }, (_, i) => ({ value: i, label: formatter.format(new Date(2024, i, 1)) }));
3390
+ }, /* @ts-ignore */
3391
+ ...(ngDevMode ? [{ debugName: "monthOptions" }] : /* istanbul ignore next */ []));
3392
+ yearOptions = computed(() => {
3393
+ const min = this.minYear();
3394
+ const max = this.maxYear();
3395
+ return Array.from({ length: max - min + 1 }, (_, i) => min + i);
3396
+ }, /* @ts-ignore */
3397
+ ...(ngDevMode ? [{ debugName: "yearOptions" }] : /* istanbul ignore next */ []));
3398
+ triggerLabel = computed(() => {
3399
+ const value = this.selected();
3400
+ return value ? new Intl.DateTimeFormat(this.locale(), { dateStyle: 'medium' }).format(value) : '';
3401
+ }, /* @ts-ignore */
3402
+ ...(ngDevMode ? [{ debugName: "triggerLabel" }] : /* istanbul ignore next */ []));
3403
+ writeValue(value) {
3404
+ this.selected.set(value);
3405
+ if (value) {
3406
+ this.focusedDate.set(value);
3407
+ this.anchorDate.set(new Date(value.getFullYear(), value.getMonth(), 1));
2913
3408
  }
2914
- this.timers.clear();
2915
3409
  }
2916
- roleFor(variant) {
2917
- return ASSERTIVE_VARIANTS.has(variant) ? 'alert' : 'status';
3410
+ registerOnChange(fn) {
3411
+ this.onChange = fn;
2918
3412
  }
2919
- iconFor(variant) {
2920
- return VARIANT_ICONS[variant];
3413
+ registerOnTouched(fn) {
3414
+ this.onTouched = fn;
2921
3415
  }
2922
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Toaster, deps: [], target: i0.ɵɵFactoryTarget.Component });
2923
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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 });
2924
- }
2925
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Toaster, decorators: [{
2926
- type: Component,
2927
- 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"] }]
2928
- }], 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"] }] } });
2929
-
2930
- const SHOW_DELAY_MS = 400;
2931
- const FADE_MS = 120;
2932
- const GAP_PX = 8;
2933
- let nextId$2 = 0;
2934
- class Tooltip {
2935
- elementRef = inject((ElementRef));
2936
- text = input.required(/* @ts-ignore */
2937
- ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
2938
- position = input('top', /* @ts-ignore */
2939
- ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
2940
- tooltipId = `gbt-tooltip-${++nextId$2}`;
2941
- visible = signal(false, /* @ts-ignore */
2942
- ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
2943
- closing = signal(false, /* @ts-ignore */
2944
- ...(ngDevMode ? [{ debugName: "closing" }] : /* istanbul ignore next */ []));
3416
+ setDisabledState(isDisabled) {
3417
+ this.formDisabled.set(isDisabled);
3418
+ }
3419
+ isSelected(date) {
3420
+ const value = this.selected();
3421
+ return value !== null && isSameDay(value, date);
3422
+ }
3423
+ isFocused(date) {
3424
+ return isSameDay(this.focusedDate(), date);
3425
+ }
3426
+ cellId(date) {
3427
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
3428
+ }
3429
+ toggleOpen() {
3430
+ if (this.isDisabled()) {
3431
+ return;
3432
+ }
3433
+ this.open.update((value) => !value);
3434
+ if (this.open()) {
3435
+ const target = this.selected() ?? new Date();
3436
+ this.focusedDate.set(target);
3437
+ this.anchorDate.set(new Date(target.getFullYear(), target.getMonth(), 1));
3438
+ this.updatePanelPosition();
3439
+ this.focusCellAfterRender();
3440
+ }
3441
+ else {
3442
+ this.onTouched();
3443
+ }
3444
+ }
3445
+ close(returnFocus) {
3446
+ if (!this.open()) {
3447
+ return;
3448
+ }
3449
+ this.open.set(false);
3450
+ this.onTouched();
3451
+ if (returnFocus) {
3452
+ this.trigger()?.focus();
3453
+ }
3454
+ }
3455
+ clear(event) {
3456
+ event.stopPropagation();
3457
+ if (this.isDisabled()) {
3458
+ return;
3459
+ }
3460
+ this.selected.set(null);
3461
+ this.onChange(null);
3462
+ this.onTouched();
3463
+ this.close(false);
3464
+ }
3465
+ selectDay(day) {
3466
+ if (this.isDisabled()) {
3467
+ return;
3468
+ }
3469
+ this.selected.set(day.date);
3470
+ this.focusedDate.set(day.date);
3471
+ this.ensureVisible(day.date);
3472
+ this.onChange(day.date);
3473
+ this.close(true);
3474
+ }
3475
+ shiftMonth(delta) {
3476
+ this.anchorDate.set(addMonths(this.anchorDate(), delta));
3477
+ this.focusedDate.set(addMonths(this.focusedDate(), delta));
3478
+ this.updatePanelPosition();
3479
+ this.focusCellAfterRender();
3480
+ }
3481
+ onMonthSelect(value) {
3482
+ this.setAnchorMonth(this.anchorDate().getFullYear(), Number(value));
3483
+ }
3484
+ onYearSelect(value) {
3485
+ this.setAnchorMonth(Number(value), this.anchorDate().getMonth());
3486
+ }
3487
+ setAnchorMonth(year, month) {
3488
+ const dayOfMonth = this.focusedDate().getDate();
3489
+ const daysInTarget = new Date(year, month + 1, 0).getDate();
3490
+ this.anchorDate.set(new Date(year, month, 1));
3491
+ this.focusedDate.set(new Date(year, month, Math.min(dayOfMonth, daysInTarget)));
3492
+ this.updatePanelPosition();
3493
+ this.focusCellAfterRender();
3494
+ }
3495
+ onGridKeydown(event) {
3496
+ const current = this.focusedDate();
3497
+ if (event.key === 'Enter' || event.key === ' ') {
3498
+ event.preventDefault();
3499
+ this.selectDay({ date: current, inCurrentMonth: true, isToday: isSameDay(current, new Date()) });
3500
+ return;
3501
+ }
3502
+ if (event.key === 'PageDown' || event.key === 'PageUp') {
3503
+ event.preventDefault();
3504
+ const delta = event.key === 'PageDown' ? 1 : -1;
3505
+ if (event.shiftKey) {
3506
+ this.anchorDate.set(addYears(this.anchorDate(), delta));
3507
+ this.focusedDate.set(addYears(current, delta));
3508
+ }
3509
+ else {
3510
+ this.anchorDate.set(addMonths(this.anchorDate(), delta));
3511
+ this.focusedDate.set(addMonths(current, delta));
3512
+ }
3513
+ this.updatePanelPosition();
3514
+ this.focusCellAfterRender();
3515
+ return;
3516
+ }
3517
+ const next = this.nextFocusedDate(current, event);
3518
+ if (next === null) {
3519
+ return;
3520
+ }
3521
+ event.preventDefault();
3522
+ this.ensureVisible(next);
3523
+ this.focusedDate.set(next);
3524
+ this.focusCellAfterRender();
3525
+ }
3526
+ nextFocusedDate(current, event) {
3527
+ switch (event.key) {
3528
+ case 'ArrowRight':
3529
+ return shiftDays$1(current, 1);
3530
+ case 'ArrowLeft':
3531
+ return shiftDays$1(current, -1);
3532
+ case 'ArrowDown':
3533
+ return shiftDays$1(current, 7);
3534
+ case 'ArrowUp':
3535
+ return shiftDays$1(current, -7);
3536
+ case 'Home':
3537
+ return startOfWeek(current, this.weekStartsOn());
3538
+ case 'End':
3539
+ return endOfWeek(current, this.weekStartsOn());
3540
+ default:
3541
+ return null;
3542
+ }
3543
+ }
3544
+ /** Shifts the anchor by the minimum amount needed so `date`'s month becomes visible. */
3545
+ ensureVisible(date) {
3546
+ const anchor = this.anchorDate();
3547
+ const visibleMonths = this.visibleMonths();
3548
+ const monthsDiff = (date.getFullYear() - anchor.getFullYear()) * 12 + (date.getMonth() - anchor.getMonth());
3549
+ if (monthsDiff < 0) {
3550
+ this.anchorDate.set(new Date(date.getFullYear(), date.getMonth(), 1));
3551
+ }
3552
+ else if (monthsDiff >= visibleMonths) {
3553
+ this.anchorDate.set(addMonths(anchor, monthsDiff - visibleMonths + 1));
3554
+ }
3555
+ }
3556
+ onEscape(event) {
3557
+ if (event.key === 'Escape' && this.open()) {
3558
+ event.preventDefault();
3559
+ event.stopPropagation();
3560
+ this.close(true);
3561
+ }
3562
+ }
3563
+ handleClickOutside(event) {
3564
+ if (this.open() && !this.elementRef.nativeElement.contains(event.target)) {
3565
+ this.close(false);
3566
+ }
3567
+ }
3568
+ updatePanelPosition() {
3569
+ if (!this.open()) {
3570
+ return;
3571
+ }
3572
+ const trigger = this.trigger();
3573
+ if (!trigger) {
3574
+ return;
3575
+ }
3576
+ const rect = trigger.getBoundingClientRect();
3577
+ this.panelStyle.set({ top: `${rect.bottom + 6}px`, left: `${rect.left}px` });
3578
+ }
3579
+ trigger() {
3580
+ return this.elementRef.nativeElement.querySelector('.gbt-date-picker__trigger');
3581
+ }
3582
+ focusCellAfterRender() {
3583
+ afterNextRender(() => {
3584
+ const id = this.cellId(this.focusedDate());
3585
+ const host = this.elementRef.nativeElement;
3586
+ host.querySelector(`[data-date="${id}"]`)?.focus();
3587
+ }, { injector: this.injector });
3588
+ }
3589
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DatePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
3590
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: DatePicker, isStandalone: true, selector: "gbt-date-picker", 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 }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, weekStartsOn: { classPropertyName: "weekStartsOn", publicName: "weekStartsOn", 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 }, previousMonthLabel: { classPropertyName: "previousMonthLabel", publicName: "previousMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, nextMonthLabel: { classPropertyName: "nextMonthLabel", publicName: "nextMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, visibleMonths: { classPropertyName: "visibleMonths", publicName: "visibleMonths", isSignal: true, isRequired: false, transformFunction: null }, monthSelectLabel: { classPropertyName: "monthSelectLabel", publicName: "monthSelectLabel", isSignal: true, isRequired: false, transformFunction: null }, yearSelectLabel: { classPropertyName: "yearSelectLabel", publicName: "yearSelectLabel", isSignal: true, isRequired: false, transformFunction: null }, minYear: { classPropertyName: "minYear", publicName: "minYear", isSignal: true, isRequired: false, transformFunction: null }, maxYear: { classPropertyName: "maxYear", publicName: "maxYear", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "handleClickOutside($event)", "keydown": "onEscape($event)", "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" } }, providers: [
3591
+ {
3592
+ provide: NG_VALUE_ACCESSOR,
3593
+ useExisting: forwardRef(() => DatePicker),
3594
+ multi: true,
3595
+ },
3596
+ ], ngImport: i0, template: "<div class=\"gbt-date-picker\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-date-picker__label\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-date-picker__field\">\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-date-picker__trigger\"\n [class.gbt-date-picker__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n <span\n class=\"gbt-date-picker__trigger-label\"\n [class.gbt-date-picker__trigger-label--placeholder]=\"!triggerLabel()\"\n >\n {{ triggerLabel() || placeholder() }}\n </span>\n </button>\n @if (showClear()) {\n <button\n type=\"button\"\n class=\"gbt-date-picker__clear\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear($event)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n } @else {\n <gbt-icon name=\"calendar\" class=\"gbt-date-picker__icon\" aria-hidden=\"true\" />\n }\n </div>\n @if (open() && panelStyle(); as pos) {\n <div\n class=\"gbt-date-picker__panel\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-label]=\"panelLabel()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n >\n <div class=\"gbt-date-picker__nav\">\n <button\n type=\"button\"\n class=\"gbt-date-picker__nav-button\"\n [attr.aria-label]=\"previousMonthLabel()\"\n (click)=\"shiftMonth(-1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n <div class=\"gbt-date-picker__headings\">\n @for (view of monthViews(); track view.year + '-' + view.month; let i = $index) {\n <div class=\"gbt-date-picker__month-heading\">\n @if (i === 0) {\n <select\n #monthSelect\n class=\"gbt-date-picker__select\"\n [attr.aria-label]=\"monthSelectLabel()\"\n (change)=\"onMonthSelect(monthSelect.value)\"\n >\n @for (opt of monthOptions(); track opt.value) {\n <option [value]=\"opt.value\" [selected]=\"opt.value === anchorDate().getMonth()\">\n {{ opt.label }}\n </option>\n }\n </select>\n <select\n #yearSelect\n class=\"gbt-date-picker__select\"\n [attr.aria-label]=\"yearSelectLabel()\"\n (change)=\"onYearSelect(yearSelect.value)\"\n >\n @for (year of yearOptions(); track year) {\n <option [value]=\"year\" [selected]=\"year === anchorDate().getFullYear()\">{{ year }}</option>\n }\n </select>\n } @else {\n <span class=\"gbt-date-picker__month-label\">{{ view.label }}</span>\n }\n </div>\n }\n </div>\n <button\n type=\"button\"\n class=\"gbt-date-picker__nav-button\"\n [attr.aria-label]=\"nextMonthLabel()\"\n (click)=\"shiftMonth(1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"gbt-date-picker__months\">\n @for (view of monthViews(); track view.year + '-' + view.month) {\n <div class=\"gbt-date-picker__month\">\n <div\n class=\"gbt-date-picker__grid\"\n role=\"grid\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.label\"\n (keydown)=\"onGridKeydown($event)\"\n >\n <div class=\"gbt-date-picker__row gbt-date-picker__row--head\" role=\"row\">\n @for (wd of weekdayLabels(); track $index) {\n <span role=\"columnheader\" class=\"gbt-date-picker__weekday\">{{ wd }}</span>\n }\n </div>\n @for (week of view.weeks; track $index) {\n <div class=\"gbt-date-picker__row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n @if (day.inCurrentMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"gbt-date-picker__day\"\n [class.gbt-date-picker__day--today]=\"day.isToday\"\n [class.gbt-date-picker__day--selected]=\"isSelected(day.date)\"\n [attr.data-date]=\"cellId(day.date)\"\n [attr.aria-selected]=\"isSelected(day.date)\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [tabIndex]=\"isFocused(day.date) ? 0 : -1\"\n (click)=\"selectDay(day)\"\n >\n {{ day.date.getDate() }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"gbt-date-picker__day gbt-date-picker__day--empty\"></span>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-date-picker__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-date-picker{display:inline-flex;flex-direction:column;gap:.375rem}.gbt-date-picker__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-date-picker__error{margin:0;font-size:.75rem;color:var(--color-error-text)}.gbt-date-picker__field{position:relative;display:inline-flex}.gbt-date-picker__trigger{box-sizing:border-box;display:flex;align-items:center;width:220px;height:40px;padding:0 34px 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)}.gbt-date-picker__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-picker__trigger:disabled{cursor:not-allowed;opacity:.5}.gbt-date-picker__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__trigger-label{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.gbt-date-picker__trigger-label--placeholder{color:var(--text-discret)}.gbt-date-picker__icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}.gbt-date-picker__clear{position:absolute;top:50%;right:6px;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;border-radius:50%;color:var(--text-secondary);cursor:pointer}.gbt-date-picker__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-picker__clear:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__panel{box-sizing:border-box;position:fixed;z-index:1000;padding:.75rem;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-date-picker-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-date-picker__nav{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.gbt-date-picker__headings{display:flex;flex:1;justify-content:center;gap:1.25rem}.gbt-date-picker__nav-button{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer}.gbt-date-picker__nav-button:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-picker__nav-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__select{box-sizing:border-box;height:28px;padding:0 6px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;font-weight:600;cursor:pointer}.gbt-date-picker__select:hover{background:var(--bg-hover)}.gbt-date-picker__select:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__months{display:flex;justify-content:center;gap:1.25rem;margin-inline:.65rem;margin-bottom:.65rem}.gbt-date-picker__month-heading{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.375rem;width:184px;height:28px}.gbt-date-picker__month-label{font-size:14px;font-weight:600;color:var(--text-primary);text-align:center}.gbt-date-picker__row{display:grid;grid-template-columns:repeat(7,32px)}.gbt-date-picker__row--head{margin-bottom:.25rem;margin-top:.25rem}.gbt-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:24px;font-size:13px;font-weight:600;color:var(--text-secondary)}.gbt-date-picker__day{box-sizing:border-box;display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;border-radius:50%;color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-date-picker__day:hover:not(:disabled):not(.gbt-date-picker__day--empty){background:var(--bg-hover)}.gbt-date-picker__day:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-date-picker__day--empty{cursor:default}.gbt-date-picker__day--today{font-weight:700;box-shadow:inset 0 0 0 1px var(--border-color)}.gbt-date-picker__day--selected{background:var(--primary);color:var(--text-on-primary);font-weight:600}@media(prefers-reduced-motion:reduce){.gbt-date-picker__panel{animation:none}.gbt-date-picker__trigger{transition:none}}@keyframes gbt-date-picker-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3597
+ }
3598
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DatePicker, decorators: [{
3599
+ type: Component,
3600
+ args: [{ selector: 'gbt-date-picker', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3601
+ '(document:click)': 'handleClickOutside($event)',
3602
+ '(keydown)': 'onEscape($event)',
3603
+ '(window:scroll)': 'updatePanelPosition()',
3604
+ '(window:resize)': 'updatePanelPosition()',
3605
+ }, providers: [
3606
+ {
3607
+ provide: NG_VALUE_ACCESSOR,
3608
+ useExisting: forwardRef(() => DatePicker),
3609
+ multi: true,
3610
+ },
3611
+ ], template: "<div class=\"gbt-date-picker\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-date-picker__label\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-date-picker__field\">\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-date-picker__trigger\"\n [class.gbt-date-picker__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n <span\n class=\"gbt-date-picker__trigger-label\"\n [class.gbt-date-picker__trigger-label--placeholder]=\"!triggerLabel()\"\n >\n {{ triggerLabel() || placeholder() }}\n </span>\n </button>\n @if (showClear()) {\n <button\n type=\"button\"\n class=\"gbt-date-picker__clear\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear($event)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n } @else {\n <gbt-icon name=\"calendar\" class=\"gbt-date-picker__icon\" aria-hidden=\"true\" />\n }\n </div>\n @if (open() && panelStyle(); as pos) {\n <div\n class=\"gbt-date-picker__panel\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-label]=\"panelLabel()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n >\n <div class=\"gbt-date-picker__nav\">\n <button\n type=\"button\"\n class=\"gbt-date-picker__nav-button\"\n [attr.aria-label]=\"previousMonthLabel()\"\n (click)=\"shiftMonth(-1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n <div class=\"gbt-date-picker__headings\">\n @for (view of monthViews(); track view.year + '-' + view.month; let i = $index) {\n <div class=\"gbt-date-picker__month-heading\">\n @if (i === 0) {\n <select\n #monthSelect\n class=\"gbt-date-picker__select\"\n [attr.aria-label]=\"monthSelectLabel()\"\n (change)=\"onMonthSelect(monthSelect.value)\"\n >\n @for (opt of monthOptions(); track opt.value) {\n <option [value]=\"opt.value\" [selected]=\"opt.value === anchorDate().getMonth()\">\n {{ opt.label }}\n </option>\n }\n </select>\n <select\n #yearSelect\n class=\"gbt-date-picker__select\"\n [attr.aria-label]=\"yearSelectLabel()\"\n (change)=\"onYearSelect(yearSelect.value)\"\n >\n @for (year of yearOptions(); track year) {\n <option [value]=\"year\" [selected]=\"year === anchorDate().getFullYear()\">{{ year }}</option>\n }\n </select>\n } @else {\n <span class=\"gbt-date-picker__month-label\">{{ view.label }}</span>\n }\n </div>\n }\n </div>\n <button\n type=\"button\"\n class=\"gbt-date-picker__nav-button\"\n [attr.aria-label]=\"nextMonthLabel()\"\n (click)=\"shiftMonth(1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"gbt-date-picker__months\">\n @for (view of monthViews(); track view.year + '-' + view.month) {\n <div class=\"gbt-date-picker__month\">\n <div\n class=\"gbt-date-picker__grid\"\n role=\"grid\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.label\"\n (keydown)=\"onGridKeydown($event)\"\n >\n <div class=\"gbt-date-picker__row gbt-date-picker__row--head\" role=\"row\">\n @for (wd of weekdayLabels(); track $index) {\n <span role=\"columnheader\" class=\"gbt-date-picker__weekday\">{{ wd }}</span>\n }\n </div>\n @for (week of view.weeks; track $index) {\n <div class=\"gbt-date-picker__row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n @if (day.inCurrentMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"gbt-date-picker__day\"\n [class.gbt-date-picker__day--today]=\"day.isToday\"\n [class.gbt-date-picker__day--selected]=\"isSelected(day.date)\"\n [attr.data-date]=\"cellId(day.date)\"\n [attr.aria-selected]=\"isSelected(day.date)\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [tabIndex]=\"isFocused(day.date) ? 0 : -1\"\n (click)=\"selectDay(day)\"\n >\n {{ day.date.getDate() }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"gbt-date-picker__day gbt-date-picker__day--empty\"></span>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-date-picker__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-date-picker{display:inline-flex;flex-direction:column;gap:.375rem}.gbt-date-picker__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-date-picker__error{margin:0;font-size:.75rem;color:var(--color-error-text)}.gbt-date-picker__field{position:relative;display:inline-flex}.gbt-date-picker__trigger{box-sizing:border-box;display:flex;align-items:center;width:220px;height:40px;padding:0 34px 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)}.gbt-date-picker__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-picker__trigger:disabled{cursor:not-allowed;opacity:.5}.gbt-date-picker__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__trigger-label{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.gbt-date-picker__trigger-label--placeholder{color:var(--text-discret)}.gbt-date-picker__icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}.gbt-date-picker__clear{position:absolute;top:50%;right:6px;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;border-radius:50%;color:var(--text-secondary);cursor:pointer}.gbt-date-picker__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-picker__clear:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__panel{box-sizing:border-box;position:fixed;z-index:1000;padding:.75rem;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-date-picker-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-date-picker__nav{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.gbt-date-picker__headings{display:flex;flex:1;justify-content:center;gap:1.25rem}.gbt-date-picker__nav-button{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer}.gbt-date-picker__nav-button:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-picker__nav-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__select{box-sizing:border-box;height:28px;padding:0 6px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;font-weight:600;cursor:pointer}.gbt-date-picker__select:hover{background:var(--bg-hover)}.gbt-date-picker__select:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-picker__months{display:flex;justify-content:center;gap:1.25rem;margin-inline:.65rem;margin-bottom:.65rem}.gbt-date-picker__month-heading{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.375rem;width:184px;height:28px}.gbt-date-picker__month-label{font-size:14px;font-weight:600;color:var(--text-primary);text-align:center}.gbt-date-picker__row{display:grid;grid-template-columns:repeat(7,32px)}.gbt-date-picker__row--head{margin-bottom:.25rem;margin-top:.25rem}.gbt-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:24px;font-size:13px;font-weight:600;color:var(--text-secondary)}.gbt-date-picker__day{box-sizing:border-box;display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;border-radius:50%;color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-date-picker__day:hover:not(:disabled):not(.gbt-date-picker__day--empty){background:var(--bg-hover)}.gbt-date-picker__day:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-date-picker__day--empty{cursor:default}.gbt-date-picker__day--today{font-weight:700;box-shadow:inset 0 0 0 1px var(--border-color)}.gbt-date-picker__day--selected{background:var(--primary);color:var(--text-on-primary);font-weight:600}@media(prefers-reduced-motion:reduce){.gbt-date-picker__panel{animation:none}.gbt-date-picker__trigger{transition:none}}@keyframes gbt-date-picker-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
3612
+ }], 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 }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], weekStartsOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStartsOn", 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 }] }], previousMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthLabel", required: false }] }], nextMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthLabel", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], visibleMonths: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleMonths", required: false }] }], monthSelectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthSelectLabel", required: false }] }], yearSelectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearSelectLabel", required: false }] }], minYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "minYear", required: false }] }], maxYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxYear", required: false }] }] } });
3613
+ function shiftDays$1(date, delta) {
3614
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + delta);
3615
+ }
3616
+
3617
+ let nextId$6 = 0;
3618
+ const CURRENT_YEAR = new Date().getFullYear();
3619
+ class DateRangePicker {
3620
+ elementRef = inject(ElementRef);
3621
+ injector = inject(Injector);
3622
+ id = input(`gbt-date-range-picker-${++nextId$6}`, /* @ts-ignore */
3623
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3624
+ label = input('', /* @ts-ignore */
3625
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3626
+ placeholder = input('Select a date range…', /* @ts-ignore */
3627
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3628
+ locale = input('en-US', /* @ts-ignore */
3629
+ ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
3630
+ weekStartsOn = input(1, /* @ts-ignore */
3631
+ ...(ngDevMode ? [{ debugName: "weekStartsOn" }] : /* istanbul ignore next */ []));
3632
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3633
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3634
+ errorMessage = input(null, /* @ts-ignore */
3635
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3636
+ previousMonthLabel = input('Previous month', /* @ts-ignore */
3637
+ ...(ngDevMode ? [{ debugName: "previousMonthLabel" }] : /* istanbul ignore next */ []));
3638
+ nextMonthLabel = input('Next month', /* @ts-ignore */
3639
+ ...(ngDevMode ? [{ debugName: "nextMonthLabel" }] : /* istanbul ignore next */ []));
3640
+ clearable = input(false, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3641
+ clearLabel = input('Clear date range', /* @ts-ignore */
3642
+ ...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
3643
+ visibleMonths = input(2, /* @ts-ignore */
3644
+ ...(ngDevMode ? [{ debugName: "visibleMonths" }] : /* istanbul ignore next */ []));
3645
+ monthSelectLabel = input('Month', /* @ts-ignore */
3646
+ ...(ngDevMode ? [{ debugName: "monthSelectLabel" }] : /* istanbul ignore next */ []));
3647
+ yearSelectLabel = input('Year', /* @ts-ignore */
3648
+ ...(ngDevMode ? [{ debugName: "yearSelectLabel" }] : /* istanbul ignore next */ []));
3649
+ minYear = input(CURRENT_YEAR - 100, /* @ts-ignore */
3650
+ ...(ngDevMode ? [{ debugName: "minYear" }] : /* istanbul ignore next */ []));
3651
+ maxYear = input(CURRENT_YEAR + 10, /* @ts-ignore */
3652
+ ...(ngDevMode ? [{ debugName: "maxYear" }] : /* istanbul ignore next */ []));
3653
+ rangeStatus = input((start, end) => {
3654
+ if (!start)
3655
+ return '';
3656
+ if (!end)
3657
+ return `${start} selected as the start date. Choose an end date.`;
3658
+ return `Date range: ${start} to ${end}.`;
3659
+ }, /* @ts-ignore */
3660
+ ...(ngDevMode ? [{ debugName: "rangeStatus" }] : /* istanbul ignore next */ []));
3661
+ open = signal(false, /* @ts-ignore */
3662
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
3663
+ value = signal(null, /* @ts-ignore */
3664
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3665
+ draftStart = signal(null, /* @ts-ignore */
3666
+ ...(ngDevMode ? [{ debugName: "draftStart" }] : /* istanbul ignore next */ []));
3667
+ draftEnd = signal(null, /* @ts-ignore */
3668
+ ...(ngDevMode ? [{ debugName: "draftEnd" }] : /* istanbul ignore next */ []));
3669
+ hoveredDate = signal(null, /* @ts-ignore */
3670
+ ...(ngDevMode ? [{ debugName: "hoveredDate" }] : /* istanbul ignore next */ []));
3671
+ focusedDate = signal(new Date(), /* @ts-ignore */
3672
+ ...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
3673
+ anchorDate = signal(new Date(), /* @ts-ignore */
3674
+ ...(ngDevMode ? [{ debugName: "anchorDate" }] : /* istanbul ignore next */ []));
3675
+ panelStyle = signal(null, /* @ts-ignore */
3676
+ ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
3677
+ formDisabled = signal(false, /* @ts-ignore */
3678
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3679
+ onChange = () => { };
3680
+ onTouched = () => { };
3681
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3682
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
3683
+ showClear = computed(() => this.clearable() && this.value() !== null && !this.isDisabled(), /* @ts-ignore */
3684
+ ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
3685
+ monthViews = computed(() => {
3686
+ const anchor = this.anchorDate();
3687
+ const count = this.visibleMonths();
3688
+ const formatter = new Intl.DateTimeFormat(this.locale(), { month: 'long', year: 'numeric' });
3689
+ const views = Array.from({ length: count }, (_, i) => {
3690
+ const monthDate = new Date(anchor.getFullYear(), anchor.getMonth() + i, 1);
3691
+ const year = monthDate.getFullYear();
3692
+ const month = monthDate.getMonth();
3693
+ const days = buildCalendarGrid(year, month, this.weekStartsOn());
3694
+ const weeks = [];
3695
+ for (let d = 0; d < days.length; d += 7) {
3696
+ weeks.push(days.slice(d, d + 7));
3697
+ }
3698
+ return { year, month, label: formatter.format(monthDate), weeks };
3699
+ });
3700
+ const neededWeeks = views.map((view) => {
3701
+ let last = view.weeks.length;
3702
+ while (last > 1 && view.weeks[last - 1].every((day) => !day.inCurrentMonth)) {
3703
+ last--;
3704
+ }
3705
+ return last;
3706
+ });
3707
+ const sharedWeeks = Math.max(...neededWeeks);
3708
+ return views.map((view) => ({ ...view, weeks: view.weeks.slice(0, sharedWeeks) }));
3709
+ }, /* @ts-ignore */
3710
+ ...(ngDevMode ? [{ debugName: "monthViews" }] : /* istanbul ignore next */ []));
3711
+ panelLabel = computed(() => {
3712
+ const views = this.monthViews();
3713
+ return views.length === 1 ? views[0].label : `${views[0].label} – ${views[views.length - 1].label}`;
3714
+ }, /* @ts-ignore */
3715
+ ...(ngDevMode ? [{ debugName: "panelLabel" }] : /* istanbul ignore next */ []));
3716
+ weekdayLabels = computed(() => weekdayLabels(this.locale(), this.weekStartsOn()), /* @ts-ignore */
3717
+ ...(ngDevMode ? [{ debugName: "weekdayLabels" }] : /* istanbul ignore next */ []));
3718
+ monthOptions = computed(() => {
3719
+ const formatter = new Intl.DateTimeFormat(this.locale(), { month: 'long' });
3720
+ return Array.from({ length: 12 }, (_, i) => ({ value: i, label: formatter.format(new Date(2024, i, 1)) }));
3721
+ }, /* @ts-ignore */
3722
+ ...(ngDevMode ? [{ debugName: "monthOptions" }] : /* istanbul ignore next */ []));
3723
+ yearOptions = computed(() => {
3724
+ const min = this.minYear();
3725
+ const max = this.maxYear();
3726
+ return Array.from({ length: max - min + 1 }, (_, i) => min + i);
3727
+ }, /* @ts-ignore */
3728
+ ...(ngDevMode ? [{ debugName: "yearOptions" }] : /* istanbul ignore next */ []));
3729
+ dateFormatter = computed(() => new Intl.DateTimeFormat(this.locale(), { dateStyle: 'medium' }), /* @ts-ignore */
3730
+ ...(ngDevMode ? [{ debugName: "dateFormatter" }] : /* istanbul ignore next */ []));
3731
+ triggerLabel = computed(() => {
3732
+ const v = this.value();
3733
+ if (!v)
3734
+ return '';
3735
+ const formatter = this.dateFormatter();
3736
+ if (!v.end)
3737
+ return formatter.format(v.start);
3738
+ return `${formatter.format(v.start)} – ${formatter.format(v.end)}`;
3739
+ }, /* @ts-ignore */
3740
+ ...(ngDevMode ? [{ debugName: "triggerLabel" }] : /* istanbul ignore next */ []));
3741
+ /** The visual [lower, upper] bounds to paint — the confirmed range once `draftEnd` is set, else a live preview against `hoveredDate`. */
3742
+ previewBounds = computed(() => {
3743
+ const start = this.draftStart();
3744
+ if (!start)
3745
+ return null;
3746
+ const other = this.draftEnd() ?? this.hoveredDate();
3747
+ if (!other)
3748
+ return null;
3749
+ return start.getTime() <= other.getTime() ? { lower: start, upper: other } : { lower: other, upper: start };
3750
+ }, /* @ts-ignore */
3751
+ ...(ngDevMode ? [{ debugName: "previewBounds" }] : /* istanbul ignore next */ []));
3752
+ isPreviewing = computed(() => this.draftStart() !== null && this.draftEnd() === null, /* @ts-ignore */
3753
+ ...(ngDevMode ? [{ debugName: "isPreviewing" }] : /* istanbul ignore next */ []));
3754
+ statusMessage = computed(() => {
3755
+ const start = this.draftStart();
3756
+ if (!start)
3757
+ return '';
3758
+ const formatter = this.dateFormatter();
3759
+ const end = this.draftEnd();
3760
+ return this.rangeStatus()(formatter.format(start), end ? formatter.format(end) : null);
3761
+ }, /* @ts-ignore */
3762
+ ...(ngDevMode ? [{ debugName: "statusMessage" }] : /* istanbul ignore next */ []));
3763
+ writeValue(value) {
3764
+ this.value.set(value);
3765
+ if (value) {
3766
+ this.focusedDate.set(value.start);
3767
+ this.anchorDate.set(new Date(value.start.getFullYear(), value.start.getMonth(), 1));
3768
+ }
3769
+ }
3770
+ registerOnChange(fn) {
3771
+ this.onChange = fn;
3772
+ }
3773
+ registerOnTouched(fn) {
3774
+ this.onTouched = fn;
3775
+ }
3776
+ setDisabledState(isDisabled) {
3777
+ this.formDisabled.set(isDisabled);
3778
+ }
3779
+ isRangeStartCap(date) {
3780
+ const bounds = this.previewBounds();
3781
+ return bounds !== null && isSameDay(date, bounds.lower);
3782
+ }
3783
+ isRangeEndCap(date) {
3784
+ const bounds = this.previewBounds();
3785
+ return bounds !== null && isSameDay(date, bounds.upper);
3786
+ }
3787
+ isInRange(date) {
3788
+ const bounds = this.previewBounds();
3789
+ return bounds !== null && date.getTime() > bounds.lower.getTime() && date.getTime() < bounds.upper.getTime();
3790
+ }
3791
+ isFocused(date) {
3792
+ return isSameDay(this.focusedDate(), date);
3793
+ }
3794
+ cellId(date) {
3795
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
3796
+ }
3797
+ toggleOpen() {
3798
+ if (this.isDisabled()) {
3799
+ return;
3800
+ }
3801
+ this.open.update((v) => !v);
3802
+ if (this.open()) {
3803
+ const value = this.value();
3804
+ const target = value?.start ?? new Date();
3805
+ this.draftStart.set(value?.start ?? null);
3806
+ this.draftEnd.set(value?.end ?? null);
3807
+ this.hoveredDate.set(null);
3808
+ this.focusedDate.set(target);
3809
+ this.anchorDate.set(new Date(target.getFullYear(), target.getMonth(), 1));
3810
+ this.updatePanelPosition();
3811
+ this.focusCellAfterRender();
3812
+ }
3813
+ else {
3814
+ this.onTouched();
3815
+ }
3816
+ }
3817
+ close(returnFocus) {
3818
+ if (!this.open()) {
3819
+ return;
3820
+ }
3821
+ this.open.set(false);
3822
+ this.onTouched();
3823
+ if (returnFocus) {
3824
+ this.trigger()?.focus();
3825
+ }
3826
+ }
3827
+ clear(event) {
3828
+ event.stopPropagation();
3829
+ if (this.isDisabled()) {
3830
+ return;
3831
+ }
3832
+ this.value.set(null);
3833
+ this.draftStart.set(null);
3834
+ this.draftEnd.set(null);
3835
+ this.onChange(null);
3836
+ this.onTouched();
3837
+ this.close(false);
3838
+ }
3839
+ selectDay(date) {
3840
+ if (this.isDisabled()) {
3841
+ return;
3842
+ }
3843
+ const start = this.draftStart();
3844
+ const complete = start !== null && this.draftEnd() !== null;
3845
+ if (!start || complete) {
3846
+ this.draftStart.set(date);
3847
+ this.draftEnd.set(null);
3848
+ this.focusedDate.set(date);
3849
+ this.ensureVisible(date);
3850
+ this.focusCellAfterRender();
3851
+ return;
3852
+ }
3853
+ const [rangeStart, rangeEnd] = start.getTime() <= date.getTime() ? [start, date] : [date, start];
3854
+ this.draftStart.set(rangeStart);
3855
+ this.draftEnd.set(rangeEnd);
3856
+ this.focusedDate.set(date);
3857
+ this.ensureVisible(date);
3858
+ const next = { start: rangeStart, end: rangeEnd };
3859
+ this.value.set(next);
3860
+ this.onChange(next);
3861
+ this.onTouched();
3862
+ this.close(true);
3863
+ }
3864
+ onDayMouseEnter(date) {
3865
+ this.hoveredDate.set(date);
3866
+ }
3867
+ onDayMouseLeave() {
3868
+ this.hoveredDate.set(null);
3869
+ }
3870
+ shiftMonth(delta) {
3871
+ this.anchorDate.set(addMonths(this.anchorDate(), delta));
3872
+ this.focusedDate.set(addMonths(this.focusedDate(), delta));
3873
+ this.updatePanelPosition();
3874
+ this.focusCellAfterRender();
3875
+ }
3876
+ onMonthSelect(value) {
3877
+ this.setAnchorMonth(this.anchorDate().getFullYear(), Number(value));
3878
+ }
3879
+ onYearSelect(value) {
3880
+ this.setAnchorMonth(Number(value), this.anchorDate().getMonth());
3881
+ }
3882
+ setAnchorMonth(year, month) {
3883
+ const dayOfMonth = this.focusedDate().getDate();
3884
+ const daysInTarget = new Date(year, month + 1, 0).getDate();
3885
+ this.anchorDate.set(new Date(year, month, 1));
3886
+ this.focusedDate.set(new Date(year, month, Math.min(dayOfMonth, daysInTarget)));
3887
+ this.updatePanelPosition();
3888
+ this.focusCellAfterRender();
3889
+ }
3890
+ onGridKeydown(event) {
3891
+ const current = this.focusedDate();
3892
+ if (event.key === 'Enter' || event.key === ' ') {
3893
+ event.preventDefault();
3894
+ this.selectDay(current);
3895
+ return;
3896
+ }
3897
+ if (event.key === 'PageDown' || event.key === 'PageUp') {
3898
+ event.preventDefault();
3899
+ const delta = event.key === 'PageDown' ? 1 : -1;
3900
+ if (event.shiftKey) {
3901
+ this.anchorDate.set(addYears(this.anchorDate(), delta));
3902
+ this.focusedDate.set(addYears(current, delta));
3903
+ }
3904
+ else {
3905
+ this.anchorDate.set(addMonths(this.anchorDate(), delta));
3906
+ this.focusedDate.set(addMonths(current, delta));
3907
+ }
3908
+ this.updatePanelPosition();
3909
+ this.focusCellAfterRender();
3910
+ return;
3911
+ }
3912
+ const next = this.nextFocusedDate(current, event);
3913
+ if (next === null) {
3914
+ return;
3915
+ }
3916
+ event.preventDefault();
3917
+ this.ensureVisible(next);
3918
+ this.focusedDate.set(next);
3919
+ this.focusCellAfterRender();
3920
+ }
3921
+ nextFocusedDate(current, event) {
3922
+ switch (event.key) {
3923
+ case 'ArrowRight':
3924
+ return shiftDays(current, 1);
3925
+ case 'ArrowLeft':
3926
+ return shiftDays(current, -1);
3927
+ case 'ArrowDown':
3928
+ return shiftDays(current, 7);
3929
+ case 'ArrowUp':
3930
+ return shiftDays(current, -7);
3931
+ case 'Home':
3932
+ return startOfWeek(current, this.weekStartsOn());
3933
+ case 'End':
3934
+ return endOfWeek(current, this.weekStartsOn());
3935
+ default:
3936
+ return null;
3937
+ }
3938
+ }
3939
+ /** Shifts the anchor by the minimum amount needed so `date`'s month becomes visible. */
3940
+ ensureVisible(date) {
3941
+ const anchor = this.anchorDate();
3942
+ const visibleMonths = this.visibleMonths();
3943
+ const monthsDiff = (date.getFullYear() - anchor.getFullYear()) * 12 + (date.getMonth() - anchor.getMonth());
3944
+ if (monthsDiff < 0) {
3945
+ this.anchorDate.set(new Date(date.getFullYear(), date.getMonth(), 1));
3946
+ }
3947
+ else if (monthsDiff >= visibleMonths) {
3948
+ this.anchorDate.set(addMonths(anchor, monthsDiff - visibleMonths + 1));
3949
+ }
3950
+ }
3951
+ onEscape(event) {
3952
+ if (event.key === 'Escape' && this.open()) {
3953
+ event.preventDefault();
3954
+ event.stopPropagation();
3955
+ this.close(true);
3956
+ }
3957
+ }
3958
+ handleClickOutside(event) {
3959
+ if (this.open() && !this.elementRef.nativeElement.contains(event.target)) {
3960
+ this.close(false);
3961
+ }
3962
+ }
3963
+ updatePanelPosition() {
3964
+ if (!this.open()) {
3965
+ return;
3966
+ }
3967
+ const trigger = this.trigger();
3968
+ if (!trigger) {
3969
+ return;
3970
+ }
3971
+ const rect = trigger.getBoundingClientRect();
3972
+ this.panelStyle.set({ top: `${rect.bottom + 6}px`, left: `${rect.left}px` });
3973
+ }
3974
+ trigger() {
3975
+ return this.elementRef.nativeElement.querySelector('.gbt-date-range-picker__trigger');
3976
+ }
3977
+ focusCellAfterRender() {
3978
+ afterNextRender(() => {
3979
+ const id = this.cellId(this.focusedDate());
3980
+ const host = this.elementRef.nativeElement;
3981
+ host.querySelector(`[data-date="${id}"]`)?.focus();
3982
+ }, { injector: this.injector });
3983
+ }
3984
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DateRangePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
3985
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: DateRangePicker, isStandalone: true, selector: "gbt-date-range-picker", 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 }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, weekStartsOn: { classPropertyName: "weekStartsOn", publicName: "weekStartsOn", 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 }, previousMonthLabel: { classPropertyName: "previousMonthLabel", publicName: "previousMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, nextMonthLabel: { classPropertyName: "nextMonthLabel", publicName: "nextMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, visibleMonths: { classPropertyName: "visibleMonths", publicName: "visibleMonths", isSignal: true, isRequired: false, transformFunction: null }, monthSelectLabel: { classPropertyName: "monthSelectLabel", publicName: "monthSelectLabel", isSignal: true, isRequired: false, transformFunction: null }, yearSelectLabel: { classPropertyName: "yearSelectLabel", publicName: "yearSelectLabel", isSignal: true, isRequired: false, transformFunction: null }, minYear: { classPropertyName: "minYear", publicName: "minYear", isSignal: true, isRequired: false, transformFunction: null }, maxYear: { classPropertyName: "maxYear", publicName: "maxYear", isSignal: true, isRequired: false, transformFunction: null }, rangeStatus: { classPropertyName: "rangeStatus", publicName: "rangeStatus", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "handleClickOutside($event)", "keydown": "onEscape($event)", "window:scroll": "updatePanelPosition()", "window:resize": "updatePanelPosition()" } }, providers: [
3986
+ {
3987
+ provide: NG_VALUE_ACCESSOR,
3988
+ useExisting: forwardRef(() => DateRangePicker),
3989
+ multi: true,
3990
+ },
3991
+ ], ngImport: i0, template: "<div class=\"gbt-date-range-picker\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-date-range-picker__label\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-date-range-picker__field\">\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-date-range-picker__trigger\"\n [class.gbt-date-range-picker__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n <span\n class=\"gbt-date-range-picker__trigger-label\"\n [class.gbt-date-range-picker__trigger-label--placeholder]=\"!triggerLabel()\"\n >\n {{ triggerLabel() || placeholder() }}\n </span>\n </button>\n @if (showClear()) {\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__clear\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear($event)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n } @else {\n <gbt-icon name=\"calendar\" class=\"gbt-date-range-picker__icon\" aria-hidden=\"true\" />\n }\n </div>\n @if (open() && panelStyle(); as pos) {\n <div\n class=\"gbt-date-range-picker__panel\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-label]=\"panelLabel()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n >\n <div class=\"gbt-date-range-picker__nav\">\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__nav-button\"\n [attr.aria-label]=\"previousMonthLabel()\"\n (click)=\"shiftMonth(-1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n <div class=\"gbt-date-range-picker__headings\">\n @for (view of monthViews(); track view.year + '-' + view.month; let i = $index) {\n <div class=\"gbt-date-range-picker__month-heading\">\n @if (i === 0) {\n <select\n #monthSelect\n class=\"gbt-date-range-picker__select\"\n [attr.aria-label]=\"monthSelectLabel()\"\n (change)=\"onMonthSelect(monthSelect.value)\"\n >\n @for (opt of monthOptions(); track opt.value) {\n <option [value]=\"opt.value\" [selected]=\"opt.value === anchorDate().getMonth()\">\n {{ opt.label }}\n </option>\n }\n </select>\n <select\n #yearSelect\n class=\"gbt-date-range-picker__select\"\n [attr.aria-label]=\"yearSelectLabel()\"\n (change)=\"onYearSelect(yearSelect.value)\"\n >\n @for (year of yearOptions(); track year) {\n <option [value]=\"year\" [selected]=\"year === anchorDate().getFullYear()\">{{ year }}</option>\n }\n </select>\n } @else {\n <span class=\"gbt-date-range-picker__month-label\">{{ view.label }}</span>\n }\n </div>\n }\n </div>\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__nav-button\"\n [attr.aria-label]=\"nextMonthLabel()\"\n (click)=\"shiftMonth(1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"gbt-date-range-picker__months\">\n @for (view of monthViews(); track view.year + '-' + view.month) {\n <div class=\"gbt-date-range-picker__month\">\n <div\n class=\"gbt-date-range-picker__grid\"\n role=\"grid\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.label\"\n (keydown)=\"onGridKeydown($event)\"\n >\n <div class=\"gbt-date-range-picker__row gbt-date-range-picker__row--head\" role=\"row\">\n @for (wd of weekdayLabels(); track $index) {\n <span role=\"columnheader\" class=\"gbt-date-range-picker__weekday\">{{ wd }}</span>\n }\n </div>\n @for (week of view.weeks; track $index) {\n <div class=\"gbt-date-range-picker__row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n @if (day.inCurrentMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"gbt-date-range-picker__day\"\n [class.gbt-date-range-picker__day--today]=\"day.isToday\"\n [class.gbt-date-range-picker__day--start-cap]=\"isRangeStartCap(day.date)\"\n [class.gbt-date-range-picker__day--end-cap]=\"isRangeEndCap(day.date)\"\n [class.gbt-date-range-picker__day--in-range]=\"isInRange(day.date)\"\n [class.gbt-date-range-picker__day--preview]=\"isPreviewing()\"\n [attr.data-date]=\"cellId(day.date)\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [tabIndex]=\"isFocused(day.date) ? 0 : -1\"\n (click)=\"selectDay(day.date)\"\n (mouseenter)=\"onDayMouseEnter(day.date)\"\n (mouseleave)=\"onDayMouseLeave()\"\n >\n {{ day.date.getDate() }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"gbt-date-range-picker__day gbt-date-range-picker__day--empty\"></span>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"gbt-sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ statusMessage() }}</div>\n </div>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-date-range-picker__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-date-range-picker{display:inline-flex;flex-direction:column;gap:.375rem}.gbt-date-range-picker__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-date-range-picker__error{margin:0;font-size:.75rem;color:var(--color-error-text)}.gbt-date-range-picker__field{position:relative;display:inline-flex}.gbt-date-range-picker__trigger{box-sizing:border-box;display:flex;align-items:center;width:260px;height:40px;padding:0 34px 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)}.gbt-date-range-picker__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-range-picker__trigger:disabled{cursor:not-allowed;opacity:.5}.gbt-date-range-picker__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__trigger-label{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.gbt-date-range-picker__trigger-label--placeholder{color:var(--text-discret)}.gbt-date-range-picker__icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}.gbt-date-range-picker__clear{position:absolute;top:50%;right:6px;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;border-radius:50%;color:var(--text-secondary);cursor:pointer}.gbt-date-range-picker__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-range-picker__clear:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__panel{box-sizing:border-box;position:fixed;z-index:1000;padding:.75rem;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-date-range-picker-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-date-range-picker__nav{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.gbt-date-range-picker__headings{display:flex;flex:1;justify-content:center;gap:1.25rem}.gbt-date-range-picker__nav-button{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer}.gbt-date-range-picker__nav-button:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-range-picker__nav-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__select{box-sizing:border-box;height:28px;padding:0 6px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;font-weight:600;cursor:pointer}.gbt-date-range-picker__select:hover{background:var(--bg-hover)}.gbt-date-range-picker__select:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__months{display:flex;justify-content:center;gap:1.25rem;margin-inline:.65rem;margin-bottom:.65rem}.gbt-date-range-picker__month-heading{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.375rem;width:184px;height:28px}.gbt-date-range-picker__month-label{font-size:14px;font-weight:600;color:var(--text-primary);text-align:center}.gbt-date-range-picker__row{display:grid;grid-template-columns:repeat(7,32px)}.gbt-date-range-picker__row--head{margin-top:.25rem;margin-bottom:.25rem}.gbt-date-range-picker__weekday{display:flex;align-items:center;justify-content:center;height:24px;font-size:13px;font-weight:600;color:var(--text-secondary)}.gbt-date-range-picker__day{position:relative;z-index:0;box-sizing:border-box;display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-date-range-picker__day:before{content:\"\";position:absolute;inset:0;z-index:-1}.gbt-date-range-picker__day:hover:not(:disabled):not(.gbt-date-range-picker__day--empty){border-radius:50%;background:var(--bg-hover)}.gbt-date-range-picker__day:focus-visible{outline:2px solid var(--primary);outline-offset:-2px;border-radius:50%}.gbt-date-range-picker__day--empty{cursor:default}.gbt-date-range-picker__day--today{font-weight:700;box-shadow:inset 0 0 0 1px var(--border-color);border-radius:50%}.gbt-date-range-picker__day--in-range:before{background:color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-range-picker__day--start-cap,.gbt-date-range-picker__day--end-cap{color:var(--text-on-primary);font-weight:600}.gbt-date-range-picker__day--start-cap:before{background:var(--primary);color:var(--text-on-primary);border-radius:50% 0 0 50%}.gbt-date-range-picker__day--end-cap:before{background:var(--primary);color:var(--text-on-primary);border-radius:0 50% 50% 0}.gbt-date-range-picker__day--start-cap.gbt-date-range-picker__day--end-cap:before{border-radius:50%}.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--in-range:before,.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--start-cap:before,.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--end-cap:before{opacity:.6}.gbt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media(prefers-reduced-motion:reduce){.gbt-date-range-picker__panel{animation:none}.gbt-date-range-picker__trigger{transition:none}}@keyframes gbt-date-range-picker-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3992
+ }
3993
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: DateRangePicker, decorators: [{
3994
+ type: Component,
3995
+ args: [{ selector: 'gbt-date-range-picker', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3996
+ '(document:click)': 'handleClickOutside($event)',
3997
+ '(keydown)': 'onEscape($event)',
3998
+ '(window:scroll)': 'updatePanelPosition()',
3999
+ '(window:resize)': 'updatePanelPosition()',
4000
+ }, providers: [
4001
+ {
4002
+ provide: NG_VALUE_ACCESSOR,
4003
+ useExisting: forwardRef(() => DateRangePicker),
4004
+ multi: true,
4005
+ },
4006
+ ], template: "<div class=\"gbt-date-range-picker\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-date-range-picker__label\">{{ label() }}{{ required() ? ' *' : '' }}</label>\n }\n <div class=\"gbt-date-range-picker__field\">\n <button\n type=\"button\"\n [id]=\"id()\"\n class=\"gbt-date-range-picker__trigger\"\n [class.gbt-date-range-picker__trigger--open]=\"open()\"\n [disabled]=\"isDisabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"toggleOpen()\"\n >\n <span\n class=\"gbt-date-range-picker__trigger-label\"\n [class.gbt-date-range-picker__trigger-label--placeholder]=\"!triggerLabel()\"\n >\n {{ triggerLabel() || placeholder() }}\n </span>\n </button>\n @if (showClear()) {\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__clear\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear($event)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n } @else {\n <gbt-icon name=\"calendar\" class=\"gbt-date-range-picker__icon\" aria-hidden=\"true\" />\n }\n </div>\n @if (open() && panelStyle(); as pos) {\n <div\n class=\"gbt-date-range-picker__panel\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-label]=\"panelLabel()\"\n [style.top]=\"pos.top\"\n [style.left]=\"pos.left\"\n >\n <div class=\"gbt-date-range-picker__nav\">\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__nav-button\"\n [attr.aria-label]=\"previousMonthLabel()\"\n (click)=\"shiftMonth(-1)\"\n >\n <gbt-icon name=\"chevron-left\" aria-hidden=\"true\" />\n </button>\n <div class=\"gbt-date-range-picker__headings\">\n @for (view of monthViews(); track view.year + '-' + view.month; let i = $index) {\n <div class=\"gbt-date-range-picker__month-heading\">\n @if (i === 0) {\n <select\n #monthSelect\n class=\"gbt-date-range-picker__select\"\n [attr.aria-label]=\"monthSelectLabel()\"\n (change)=\"onMonthSelect(monthSelect.value)\"\n >\n @for (opt of monthOptions(); track opt.value) {\n <option [value]=\"opt.value\" [selected]=\"opt.value === anchorDate().getMonth()\">\n {{ opt.label }}\n </option>\n }\n </select>\n <select\n #yearSelect\n class=\"gbt-date-range-picker__select\"\n [attr.aria-label]=\"yearSelectLabel()\"\n (change)=\"onYearSelect(yearSelect.value)\"\n >\n @for (year of yearOptions(); track year) {\n <option [value]=\"year\" [selected]=\"year === anchorDate().getFullYear()\">{{ year }}</option>\n }\n </select>\n } @else {\n <span class=\"gbt-date-range-picker__month-label\">{{ view.label }}</span>\n }\n </div>\n }\n </div>\n <button\n type=\"button\"\n class=\"gbt-date-range-picker__nav-button\"\n [attr.aria-label]=\"nextMonthLabel()\"\n (click)=\"shiftMonth(1)\"\n >\n <gbt-icon name=\"chevron-right\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"gbt-date-range-picker__months\">\n @for (view of monthViews(); track view.year + '-' + view.month) {\n <div class=\"gbt-date-range-picker__month\">\n <div\n class=\"gbt-date-range-picker__grid\"\n role=\"grid\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.label\"\n (keydown)=\"onGridKeydown($event)\"\n >\n <div class=\"gbt-date-range-picker__row gbt-date-range-picker__row--head\" role=\"row\">\n @for (wd of weekdayLabels(); track $index) {\n <span role=\"columnheader\" class=\"gbt-date-range-picker__weekday\">{{ wd }}</span>\n }\n </div>\n @for (week of view.weeks; track $index) {\n <div class=\"gbt-date-range-picker__row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n @if (day.inCurrentMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"gbt-date-range-picker__day\"\n [class.gbt-date-range-picker__day--today]=\"day.isToday\"\n [class.gbt-date-range-picker__day--start-cap]=\"isRangeStartCap(day.date)\"\n [class.gbt-date-range-picker__day--end-cap]=\"isRangeEndCap(day.date)\"\n [class.gbt-date-range-picker__day--in-range]=\"isInRange(day.date)\"\n [class.gbt-date-range-picker__day--preview]=\"isPreviewing()\"\n [attr.data-date]=\"cellId(day.date)\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [tabIndex]=\"isFocused(day.date) ? 0 : -1\"\n (click)=\"selectDay(day.date)\"\n (mouseenter)=\"onDayMouseEnter(day.date)\"\n (mouseleave)=\"onDayMouseLeave()\"\n >\n {{ day.date.getDate() }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"gbt-date-range-picker__day gbt-date-range-picker__day--empty\"></span>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <div class=\"gbt-sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ statusMessage() }}</div>\n </div>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-date-range-picker__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-date-range-picker{display:inline-flex;flex-direction:column;gap:.375rem}.gbt-date-range-picker__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-date-range-picker__error{margin:0;font-size:.75rem;color:var(--color-error-text)}.gbt-date-range-picker__field{position:relative;display:inline-flex}.gbt-date-range-picker__trigger{box-sizing:border-box;display:flex;align-items:center;width:260px;height:40px;padding:0 34px 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)}.gbt-date-range-picker__trigger--open{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-range-picker__trigger:disabled{cursor:not-allowed;opacity:.5}.gbt-date-range-picker__trigger:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__trigger-label{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.gbt-date-range-picker__trigger-label--placeholder{color:var(--text-discret)}.gbt-date-range-picker__icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}.gbt-date-range-picker__clear{position:absolute;top:50%;right:6px;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;border-radius:50%;color:var(--text-secondary);cursor:pointer}.gbt-date-range-picker__clear:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-range-picker__clear:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__panel{box-sizing:border-box;position:fixed;z-index:1000;padding:.75rem;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-date-range-picker-scale-in .15s cubic-bezier(.34,1.56,.64,1) both}.gbt-date-range-picker__nav{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.gbt-date-range-picker__headings{display:flex;flex:1;justify-content:center;gap:1.25rem}.gbt-date-range-picker__nav-button{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer}.gbt-date-range-picker__nav-button:hover{background:var(--bg-hover);color:var(--text-primary)}.gbt-date-range-picker__nav-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__select{box-sizing:border-box;height:28px;padding:0 6px;background:none;border:none;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;font-weight:600;cursor:pointer}.gbt-date-range-picker__select:hover{background:var(--bg-hover)}.gbt-date-range-picker__select:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-date-range-picker__months{display:flex;justify-content:center;gap:1.25rem;margin-inline:.65rem;margin-bottom:.65rem}.gbt-date-range-picker__month-heading{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:.375rem;width:184px;height:28px}.gbt-date-range-picker__month-label{font-size:14px;font-weight:600;color:var(--text-primary);text-align:center}.gbt-date-range-picker__row{display:grid;grid-template-columns:repeat(7,32px)}.gbt-date-range-picker__row--head{margin-top:.25rem;margin-bottom:.25rem}.gbt-date-range-picker__weekday{display:flex;align-items:center;justify-content:center;height:24px;font-size:13px;font-weight:600;color:var(--text-secondary)}.gbt-date-range-picker__day{position:relative;z-index:0;box-sizing:border-box;display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-date-range-picker__day:before{content:\"\";position:absolute;inset:0;z-index:-1}.gbt-date-range-picker__day:hover:not(:disabled):not(.gbt-date-range-picker__day--empty){border-radius:50%;background:var(--bg-hover)}.gbt-date-range-picker__day:focus-visible{outline:2px solid var(--primary);outline-offset:-2px;border-radius:50%}.gbt-date-range-picker__day--empty{cursor:default}.gbt-date-range-picker__day--today{font-weight:700;box-shadow:inset 0 0 0 1px var(--border-color);border-radius:50%}.gbt-date-range-picker__day--in-range:before{background:color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-date-range-picker__day--start-cap,.gbt-date-range-picker__day--end-cap{color:var(--text-on-primary);font-weight:600}.gbt-date-range-picker__day--start-cap:before{background:var(--primary);color:var(--text-on-primary);border-radius:50% 0 0 50%}.gbt-date-range-picker__day--end-cap:before{background:var(--primary);color:var(--text-on-primary);border-radius:0 50% 50% 0}.gbt-date-range-picker__day--start-cap.gbt-date-range-picker__day--end-cap:before{border-radius:50%}.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--in-range:before,.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--start-cap:before,.gbt-date-range-picker__day--preview.gbt-date-range-picker__day--end-cap:before{opacity:.6}.gbt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media(prefers-reduced-motion:reduce){.gbt-date-range-picker__panel{animation:none}.gbt-date-range-picker__trigger{transition:none}}@keyframes gbt-date-range-picker-scale-in{0%{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
4007
+ }], 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 }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], weekStartsOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStartsOn", 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 }] }], previousMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthLabel", required: false }] }], nextMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthLabel", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], visibleMonths: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleMonths", required: false }] }], monthSelectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthSelectLabel", required: false }] }], yearSelectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearSelectLabel", required: false }] }], minYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "minYear", required: false }] }], maxYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxYear", required: false }] }], rangeStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeStatus", required: false }] }] } });
4008
+ function shiftDays(date, delta) {
4009
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + delta);
4010
+ }
4011
+
4012
+ class AccordionItem {
4013
+ parent = inject(Accordion);
4014
+ header = viewChild('header', /* @ts-ignore */
4015
+ ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
4016
+ label = input.required(/* @ts-ignore */
4017
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4018
+ active = signal(false, /* @ts-ignore */
4019
+ ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
4020
+ index = signal(0, /* @ts-ignore */
4021
+ ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
4022
+ groupId = signal('', /* @ts-ignore */
4023
+ ...(ngDevMode ? [{ debugName: "groupId" }] : /* istanbul ignore next */ []));
4024
+ headerId = computed(() => `${this.groupId()}-header-${this.index()}`, /* @ts-ignore */
4025
+ ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
4026
+ panelId = computed(() => `${this.groupId()}-panel-${this.index()}`, /* @ts-ignore */
4027
+ ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
4028
+ setState(index, active, groupId) {
4029
+ this.index.set(index);
4030
+ this.active.set(active);
4031
+ this.groupId.set(groupId);
4032
+ }
4033
+ focusHeader() {
4034
+ this.header()?.nativeElement.focus();
4035
+ }
4036
+ toggle() {
4037
+ this.parent.toggle(this.index());
4038
+ }
4039
+ onKeydown(event) {
4040
+ if (event.key === 'ArrowDown') {
4041
+ event.preventDefault();
4042
+ this.parent.focusHeader(this.index() + 1);
4043
+ }
4044
+ else if (event.key === 'ArrowUp') {
4045
+ event.preventDefault();
4046
+ this.parent.focusHeader(this.index() - 1);
4047
+ }
4048
+ }
4049
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AccordionItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
4050
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.6", type: AccordionItem, isStandalone: true, selector: "gbt-accordion-item", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true, isSignal: true }], ngImport: i0, template: "<button\n #header\n type=\"button\"\n class=\"gbt-accordion-item__header\"\n [class.gbt-accordion-item__header--open]=\"active()\"\n [id]=\"headerId()\"\n [attr.aria-expanded]=\"active()\"\n [attr.aria-controls]=\"panelId()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n>\n <span class=\"gbt-accordion-item__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-accordion-item__chevron\" aria-hidden=\"true\" />\n</button>\n<div\n class=\"gbt-accordion-item__panel\"\n [class.gbt-accordion-item__panel--open]=\"active()\"\n [id]=\"panelId()\"\n [attr.aria-labelledby]=\"headerId()\"\n [attr.inert]=\"active() ? null : ''\"\n>\n <div class=\"gbt-accordion-item__panel-inner\">\n <div class=\"gbt-accordion-item__panel-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}:host:not(:last-child){border-bottom:1px solid var(--border-color)}.gbt-accordion-item__header{box-sizing:border-box;display:flex;align-items:center;gap:.75rem;width:100%;padding:.875rem 1rem;background:var(--bg-principal);border:none;color:var(--text-primary);font-size:14px;font-weight:600;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__header:hover{background:var(--bg-hover)}.gbt-accordion-item__header:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-accordion-item__label{flex:1;min-width:0}.gbt-accordion-item__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__header--open .gbt-accordion-item__chevron{transform:rotate(180deg)}.gbt-accordion-item__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__panel--open{grid-template-rows:1fr}.gbt-accordion-item__panel-inner{overflow:hidden;min-height:0}.gbt-accordion-item__panel-content{padding:1rem}@media(prefers-reduced-motion:reduce){.gbt-accordion-item__chevron,.gbt-accordion-item__panel{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4051
+ }
4052
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AccordionItem, decorators: [{
4053
+ type: Component,
4054
+ args: [{ selector: 'gbt-accordion-item', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n #header\n type=\"button\"\n class=\"gbt-accordion-item__header\"\n [class.gbt-accordion-item__header--open]=\"active()\"\n [id]=\"headerId()\"\n [attr.aria-expanded]=\"active()\"\n [attr.aria-controls]=\"panelId()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n>\n <span class=\"gbt-accordion-item__label\">{{ label() }}</span>\n <gbt-icon name=\"chevron-down\" class=\"gbt-accordion-item__chevron\" aria-hidden=\"true\" />\n</button>\n<div\n class=\"gbt-accordion-item__panel\"\n [class.gbt-accordion-item__panel--open]=\"active()\"\n [id]=\"panelId()\"\n [attr.aria-labelledby]=\"headerId()\"\n [attr.inert]=\"active() ? null : ''\"\n>\n <div class=\"gbt-accordion-item__panel-inner\">\n <div class=\"gbt-accordion-item__panel-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}:host:not(:last-child){border-bottom:1px solid var(--border-color)}.gbt-accordion-item__header{box-sizing:border-box;display:flex;align-items:center;gap:.75rem;width:100%;padding:.875rem 1rem;background:var(--bg-principal);border:none;color:var(--text-primary);font-size:14px;font-weight:600;text-align:left;cursor:pointer;transition:background .12s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__header:hover{background:var(--bg-hover)}.gbt-accordion-item__header:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-accordion-item__label{flex:1;min-width:0}.gbt-accordion-item__chevron{flex-shrink:0;color:var(--text-secondary);transition:transform .2s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__header--open .gbt-accordion-item__chevron{transform:rotate(180deg)}.gbt-accordion-item__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s cubic-bezier(.4,0,.2,1)}.gbt-accordion-item__panel--open{grid-template-rows:1fr}.gbt-accordion-item__panel-inner{overflow:hidden;min-height:0}.gbt-accordion-item__panel-content{padding:1rem}@media(prefers-reduced-motion:reduce){.gbt-accordion-item__chevron,.gbt-accordion-item__panel{transition:none}}\n"] }]
4055
+ }], propDecorators: { header: [{ type: i0.ViewChild, args: ['header', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }] } });
4056
+
4057
+ let nextAccordionId = 0;
4058
+ class Accordion {
4059
+ id = input(`gbt-accordion-${++nextAccordionId}`, /* @ts-ignore */
4060
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4061
+ mode = input('single', /* @ts-ignore */
4062
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
4063
+ expanded = model([], /* @ts-ignore */
4064
+ ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
4065
+ items = contentChildren(AccordionItem, /* @ts-ignore */
4066
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
4067
+ constructor() {
4068
+ effect(() => {
4069
+ const items = this.items();
4070
+ const expanded = this.expanded();
4071
+ const groupId = this.id();
4072
+ items.forEach((item, i) => item.setState(i, expanded.includes(i), groupId));
4073
+ });
4074
+ }
4075
+ toggle(index) {
4076
+ const current = this.expanded();
4077
+ if (this.mode() === 'single') {
4078
+ this.expanded.set(current.includes(index) ? [] : [index]);
4079
+ return;
4080
+ }
4081
+ this.expanded.set(current.includes(index) ? current.filter((i) => i !== index) : [...current, index]);
4082
+ }
4083
+ focusHeader(index) {
4084
+ const items = this.items();
4085
+ const count = items.length;
4086
+ if (count === 0) {
4087
+ return;
4088
+ }
4089
+ const wrapped = ((index % count) + count) % count;
4090
+ items[wrapped]?.focusHeader();
4091
+ }
4092
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Accordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
4093
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.6", type: Accordion, isStandalone: true, selector: "gbt-accordion", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, queries: [{ propertyName: "items", predicate: AccordionItem, isSignal: true }], ngImport: i0, template: `
4094
+ <div class="gbt-accordion">
4095
+ <ng-content></ng-content>
4096
+ </div>
4097
+ `, isInline: true, styles: [".gbt-accordion{display:block;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4098
+ }
4099
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Accordion, decorators: [{
4100
+ type: Component,
4101
+ args: [{ selector: 'gbt-accordion', standalone: true, imports: [], template: `
4102
+ <div class="gbt-accordion">
4103
+ <ng-content></ng-content>
4104
+ </div>
4105
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".gbt-accordion{display:block;border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);overflow:hidden}\n"] }]
4106
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AccordionItem), { isSignal: true }] }] } });
4107
+
4108
+ const ELLIPSIS = '…';
4109
+ function range(start, end) {
4110
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
4111
+ }
4112
+ function paginationRange(page, pageCount, siblingCount) {
4113
+ const totalPageNumbers = siblingCount + 5;
4114
+ if (totalPageNumbers >= pageCount) {
4115
+ return range(1, pageCount);
4116
+ }
4117
+ const leftSiblingIndex = Math.max(page - siblingCount, 1);
4118
+ const rightSiblingIndex = Math.min(page + siblingCount, pageCount);
4119
+ const shouldShowLeftDots = leftSiblingIndex > 2;
4120
+ // -2, not -1: a lone skipped page right before the last one isn't worth an
4121
+ // ellipsis — showing that page costs no more room than the "…" would.
4122
+ const shouldShowRightDots = rightSiblingIndex < pageCount - 2;
4123
+ if (!shouldShowLeftDots && shouldShowRightDots) {
4124
+ const leftItemCount = 3 + siblingCount * 2;
4125
+ return [...range(1, leftItemCount), ELLIPSIS, pageCount];
4126
+ }
4127
+ if (shouldShowLeftDots && !shouldShowRightDots) {
4128
+ const rightItemCount = 3 + siblingCount * 2;
4129
+ return [1, ELLIPSIS, ...range(pageCount - rightItemCount + 1, pageCount)];
4130
+ }
4131
+ return [1, ELLIPSIS, ...range(leftSiblingIndex, rightSiblingIndex), ELLIPSIS, pageCount];
4132
+ }
4133
+ class Pagination {
4134
+ page = input(1, /* @ts-ignore */
4135
+ ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
4136
+ pageSize = input(10, /* @ts-ignore */
4137
+ ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
4138
+ totalItems = input.required(/* @ts-ignore */
4139
+ ...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
4140
+ siblingCount = input(1, /* @ts-ignore */
4141
+ ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
4142
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4143
+ ariaLabel = input('Pagination', /* @ts-ignore */
4144
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4145
+ previousLabel = input('Previous page', /* @ts-ignore */
4146
+ ...(ngDevMode ? [{ debugName: "previousLabel" }] : /* istanbul ignore next */ []));
4147
+ nextLabel = input('Next page', /* @ts-ignore */
4148
+ ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
4149
+ pageLabel = input((page) => `Page ${page}`, /* @ts-ignore */
4150
+ ...(ngDevMode ? [{ debugName: "pageLabel" }] : /* istanbul ignore next */ []));
4151
+ pageSizeOptions = input([], /* @ts-ignore */
4152
+ ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
4153
+ pageSizeLabel = input((size) => `${size} / page`, /* @ts-ignore */
4154
+ ...(ngDevMode ? [{ debugName: "pageSizeLabel" }] : /* istanbul ignore next */ []));
4155
+ pageSizeSelectLabel = input('Rows per page', /* @ts-ignore */
4156
+ ...(ngDevMode ? [{ debugName: "pageSizeSelectLabel" }] : /* istanbul ignore next */ []));
4157
+ showItemsSummary = input(false, { ...(ngDevMode ? { debugName: "showItemsSummary" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4158
+ itemsSummaryLabel = input((shown, total) => `${shown} of ${total} items`, /* @ts-ignore */
4159
+ ...(ngDevMode ? [{ debugName: "itemsSummaryLabel" }] : /* istanbul ignore next */ []));
4160
+ pageChange = output();
4161
+ pageSizeChange = output();
4162
+ ELLIPSIS = ELLIPSIS;
4163
+ pageCount = computed(() => Math.max(1, Math.ceil(this.totalItems() / this.pageSize())), /* @ts-ignore */
4164
+ ...(ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []));
4165
+ items = computed(() => paginationRange(this.page(), this.pageCount(), this.siblingCount()), /* @ts-ignore */
4166
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
4167
+ itemsShown = computed(() => {
4168
+ const start = (this.page() - 1) * this.pageSize();
4169
+ return Math.max(0, Math.min(this.pageSize(), this.totalItems() - start));
4170
+ }, /* @ts-ignore */
4171
+ ...(ngDevMode ? [{ debugName: "itemsShown" }] : /* istanbul ignore next */ []));
4172
+ itemsSummary = computed(() => this.itemsSummaryLabel()(this.itemsShown(), this.totalItems()), /* @ts-ignore */
4173
+ ...(ngDevMode ? [{ debugName: "itemsSummary" }] : /* istanbul ignore next */ []));
4174
+ pageSizeSelectOptions = computed(() => this.pageSizeOptions().map((size) => ({ value: size, label: this.pageSizeLabel()(size) })), /* @ts-ignore */
4175
+ ...(ngDevMode ? [{ debugName: "pageSizeSelectOptions" }] : /* istanbul ignore next */ []));
4176
+ pageSizeControl = new FormControl(this.pageSize(), {
4177
+ nonNullable: true,
4178
+ });
4179
+ constructor() {
4180
+ effect(() => {
4181
+ const size = this.pageSize();
4182
+ if (this.pageSizeControl.value !== size) {
4183
+ this.pageSizeControl.setValue(size, { emitEvent: false });
4184
+ }
4185
+ });
4186
+ this.pageSizeControl.valueChanges.pipe(takeUntilDestroyed()).subscribe((size) => {
4187
+ this.pageSizeChange.emit(size);
4188
+ this.pageChange.emit(1);
4189
+ });
4190
+ // Self-heals a stale `page` — e.g. a filter shrinks `totalItems` while
4191
+ // the app was sitting on a now out-of-range page — instead of leaving
4192
+ // the pager stuck with no page marked current and a live "previous"
4193
+ // button pointing at a page that no longer exists.
4194
+ effect(() => {
4195
+ const count = this.pageCount();
4196
+ const current = this.page();
4197
+ const clamped = Math.min(Math.max(current, 1), count);
4198
+ if (clamped !== current) {
4199
+ this.pageChange.emit(clamped);
4200
+ }
4201
+ });
4202
+ }
4203
+ goTo(page) {
4204
+ if (this.disabled())
4205
+ return;
4206
+ const clamped = Math.min(Math.max(page, 1), this.pageCount());
4207
+ if (clamped === this.page())
4208
+ return;
4209
+ this.pageChange.emit(clamped);
4210
+ }
4211
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Pagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
4212
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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", "chips", "placeholder", "disabled", "required", "errorMessage", "selectedCountLabel", "chipRemoveLabel"] }, { 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 });
4213
+ }
4214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Pagination, decorators: [{
4215
+ type: Component,
4216
+ 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"] }]
4217
+ }], 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"] }] } });
4218
+
4219
+ class Breadcrumb {
4220
+ ariaLabel = input.required(/* @ts-ignore */
4221
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4222
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Breadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
4223
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", 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 });
4224
+ }
4225
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Breadcrumb, decorators: [{
4226
+ type: Component,
4227
+ 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"] }]
4228
+ }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }] } });
4229
+
4230
+ class ConfirmDangerModal {
4231
+ isOpen = input.required(/* @ts-ignore */
4232
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
4233
+ heading = input.required(/* @ts-ignore */
4234
+ ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
4235
+ message = input.required(/* @ts-ignore */
4236
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
4237
+ confirmText = input.required(/* @ts-ignore */
4238
+ ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
4239
+ confirmInputLabel = input('Type to confirm', /* @ts-ignore */
4240
+ ...(ngDevMode ? [{ debugName: "confirmInputLabel" }] : /* istanbul ignore next */ []));
4241
+ confirmLabel = input('Confirm', /* @ts-ignore */
4242
+ ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
4243
+ cancelLabel = input('Cancel', /* @ts-ignore */
4244
+ ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
4245
+ closeLabel = input('Close', /* @ts-ignore */
4246
+ ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
4247
+ confirmed = output();
4248
+ closed = output();
4249
+ typed = signal('', /* @ts-ignore */
4250
+ ...(ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []));
4251
+ canConfirm = computed(() => this.typed().length > 0 && this.typed() === this.confirmText(), /* @ts-ignore */
4252
+ ...(ngDevMode ? [{ debugName: "canConfirm" }] : /* istanbul ignore next */ []));
4253
+ constructor() {
4254
+ // Cleared whenever the modal transitions to closed (Cancel, Escape,
4255
+ // backdrop, or the consumer setting isOpen false after a successful
4256
+ // confirm) — a later reopen must never show the previous attempt's text.
4257
+ effect(() => {
4258
+ if (!this.isOpen()) {
4259
+ this.typed.set('');
4260
+ }
4261
+ });
4262
+ }
4263
+ confirm() {
4264
+ if (this.canConfirm()) {
4265
+ this.confirmed.emit();
4266
+ }
4267
+ }
4268
+ cancel() {
4269
+ this.closed.emit();
4270
+ }
4271
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ConfirmDangerModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
4272
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", 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 });
4273
+ }
4274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ConfirmDangerModal, decorators: [{
4275
+ type: Component,
4276
+ 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"] }]
4277
+ }], 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"] }] } });
4278
+
4279
+ const DEFAULT_DURATION_MS = 5000;
4280
+ const ASSERTIVE_VARIANTS = new Set(['warning', 'error']);
4281
+ const VARIANT_ICONS = {
4282
+ success: 'check-circle',
4283
+ error: 'alert-circle',
4284
+ warning: 'alert-triangle',
4285
+ info: 'info',
4286
+ };
4287
+ class Toaster {
4288
+ toasts = input.required(/* @ts-ignore */
4289
+ ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
4290
+ position = input('bottom-right', /* @ts-ignore */
4291
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
4292
+ closeLabel = input('Close', /* @ts-ignore */
4293
+ ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
4294
+ dismissed = output();
4295
+ timers = new Map();
4296
+ constructor() {
4297
+ effect(() => {
4298
+ const currentIds = new Set(this.toasts().map((toast) => toast.id));
4299
+ for (const [id, timer] of this.timers) {
4300
+ if (!currentIds.has(id)) {
4301
+ clearTimeout(timer);
4302
+ this.timers.delete(id);
4303
+ }
4304
+ }
4305
+ for (const toast of this.toasts()) {
4306
+ if (this.timers.has(toast.id)) {
4307
+ continue;
4308
+ }
4309
+ const duration = toast.duration ?? DEFAULT_DURATION_MS;
4310
+ if (!Number.isFinite(duration) || duration <= 0) {
4311
+ continue;
4312
+ }
4313
+ this.timers.set(toast.id, setTimeout(() => {
4314
+ this.timers.delete(toast.id);
4315
+ this.dismissed.emit(toast.id);
4316
+ }, duration));
4317
+ }
4318
+ });
4319
+ }
4320
+ ngOnDestroy() {
4321
+ for (const timer of this.timers.values()) {
4322
+ clearTimeout(timer);
4323
+ }
4324
+ this.timers.clear();
4325
+ }
4326
+ roleFor(variant) {
4327
+ return ASSERTIVE_VARIANTS.has(variant) ? 'alert' : 'status';
4328
+ }
4329
+ iconFor(variant) {
4330
+ return VARIANT_ICONS[variant];
4331
+ }
4332
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Toaster, deps: [], target: i0.ɵɵFactoryTarget.Component });
4333
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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 });
4334
+ }
4335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Toaster, decorators: [{
4336
+ type: Component,
4337
+ 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"] }]
4338
+ }], 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"] }] } });
4339
+
4340
+ const SHOW_DELAY_MS = 400;
4341
+ const FADE_MS = 120;
4342
+ const GAP_PX = 8;
4343
+ let nextId$5 = 0;
4344
+ class Tooltip {
4345
+ elementRef = inject((ElementRef));
4346
+ text = input.required(/* @ts-ignore */
4347
+ ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
4348
+ position = input('top', /* @ts-ignore */
4349
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
4350
+ tooltipId = `gbt-tooltip-${++nextId$5}`;
4351
+ visible = signal(false, /* @ts-ignore */
4352
+ ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
4353
+ closing = signal(false, /* @ts-ignore */
4354
+ ...(ngDevMode ? [{ debugName: "closing" }] : /* istanbul ignore next */ []));
2945
4355
  coords = signal(null, /* @ts-ignore */
2946
4356
  ...(ngDevMode ? [{ debugName: "coords" }] : /* istanbul ignore next */ []));
2947
4357
  showTimer = null;
@@ -2952,155 +4362,553 @@ class Tooltip {
2952
4362
  this.show();
2953
4363
  }, SHOW_DELAY_MS);
2954
4364
  }
2955
- onFocusIn() {
2956
- this.show();
4365
+ onFocusIn() {
4366
+ this.show();
4367
+ }
4368
+ show() {
4369
+ if (this.hideTimer !== null) {
4370
+ clearTimeout(this.hideTimer);
4371
+ this.hideTimer = null;
4372
+ }
4373
+ this.closing.set(false);
4374
+ this.updatePosition();
4375
+ this.visible.set(true);
4376
+ }
4377
+ updatePosition() {
4378
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
4379
+ switch (this.position()) {
4380
+ case 'top':
4381
+ this.coords.set({ top: rect.top - GAP_PX, left: rect.left + rect.width / 2 });
4382
+ break;
4383
+ case 'bottom':
4384
+ this.coords.set({ top: rect.bottom + GAP_PX, left: rect.left + rect.width / 2 });
4385
+ break;
4386
+ case 'left':
4387
+ this.coords.set({ top: rect.top + rect.height / 2, left: rect.left - GAP_PX });
4388
+ break;
4389
+ case 'right':
4390
+ this.coords.set({ top: rect.top + rect.height / 2, left: rect.right + GAP_PX });
4391
+ break;
4392
+ }
4393
+ }
4394
+ hide() {
4395
+ if (this.showTimer !== null) {
4396
+ clearTimeout(this.showTimer);
4397
+ this.showTimer = null;
4398
+ }
4399
+ if (!this.visible() || this.closing())
4400
+ return;
4401
+ this.closing.set(true);
4402
+ this.hideTimer = setTimeout(() => {
4403
+ this.hideTimer = null;
4404
+ this.closing.set(false);
4405
+ this.visible.set(false);
4406
+ }, FADE_MS);
4407
+ }
4408
+ ngOnDestroy() {
4409
+ if (this.showTimer !== null) {
4410
+ clearTimeout(this.showTimer);
4411
+ this.showTimer = null;
4412
+ }
4413
+ if (this.hideTimer !== null) {
4414
+ clearTimeout(this.hideTimer);
4415
+ this.hideTimer = null;
4416
+ }
4417
+ }
4418
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tooltip, deps: [], target: i0.ɵɵFactoryTarget.Component });
4419
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Tooltip, isStandalone: true, selector: "gbt-tooltip", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "hide()", "focusin": "onFocusIn()", "focusout": "hide()", "keydown.escape": "hide()", "window:scroll": "updatePosition()", "window:resize": "updatePosition()" }, classAttribute: "gbt-tooltip-host" }, exportAs: ["gbtTooltip"], ngImport: i0, template: "<ng-content />\n@if (visible() && coords(); as pos) {\n <span\n class=\"gbt-tooltip__bubble\"\n [class.gbt-tooltip__bubble--leaving]=\"closing()\"\n role=\"tooltip\"\n [id]=\"tooltipId\"\n [attr.data-position]=\"position()\"\n [style.top.px]=\"pos.top\"\n [style.left.px]=\"pos.left\"\n >\n {{ text() }}\n </span>\n}", styles: [".gbt-tooltip-host{display:inline-block}.gbt-tooltip__bubble{position:fixed;z-index:1100;max-width:240px;padding:.375rem .625rem;background:var(--bg-inverse);color:var(--text-on-color);text-align:center;white-space:normal;border:1px solid rgba(255,255,255,.15);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-md);font-size:.8125rem;line-height:1.3;pointer-events:none}.gbt-tooltip__bubble[data-position=top]{transform:translate(-50%,-100%)}.gbt-tooltip__bubble[data-position=bottom]{transform:translate(-50%)}.gbt-tooltip__bubble[data-position=left]{transform:translate(-100%,-50%)}.gbt-tooltip__bubble[data-position=right]{transform:translateY(-50%)}.gbt-tooltip__bubble{animation:gbt-tooltip-fade-in .12s ease-out}.gbt-tooltip__bubble.gbt-tooltip__bubble--leaving{animation:gbt-tooltip-fade-out .12s ease-in forwards}@keyframes gbt-tooltip-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-tooltip-fade-out{0%{opacity:1}to{opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4420
+ }
4421
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tooltip, decorators: [{
4422
+ type: Component,
4423
+ args: [{ selector: 'gbt-tooltip', standalone: true, exportAs: 'gbtTooltip', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
4424
+ class: 'gbt-tooltip-host',
4425
+ '(mouseenter)': 'onMouseEnter()',
4426
+ '(mouseleave)': 'hide()',
4427
+ '(focusin)': 'onFocusIn()',
4428
+ '(focusout)': 'hide()',
4429
+ '(keydown.escape)': 'hide()',
4430
+ '(window:scroll)': 'updatePosition()',
4431
+ '(window:resize)': 'updatePosition()',
4432
+ }, template: "<ng-content />\n@if (visible() && coords(); as pos) {\n <span\n class=\"gbt-tooltip__bubble\"\n [class.gbt-tooltip__bubble--leaving]=\"closing()\"\n role=\"tooltip\"\n [id]=\"tooltipId\"\n [attr.data-position]=\"position()\"\n [style.top.px]=\"pos.top\"\n [style.left.px]=\"pos.left\"\n >\n {{ text() }}\n </span>\n}", styles: [".gbt-tooltip-host{display:inline-block}.gbt-tooltip__bubble{position:fixed;z-index:1100;max-width:240px;padding:.375rem .625rem;background:var(--bg-inverse);color:var(--text-on-color);text-align:center;white-space:normal;border:1px solid rgba(255,255,255,.15);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-md);font-size:.8125rem;line-height:1.3;pointer-events:none}.gbt-tooltip__bubble[data-position=top]{transform:translate(-50%,-100%)}.gbt-tooltip__bubble[data-position=bottom]{transform:translate(-50%)}.gbt-tooltip__bubble[data-position=left]{transform:translate(-100%,-50%)}.gbt-tooltip__bubble[data-position=right]{transform:translateY(-50%)}.gbt-tooltip__bubble{animation:gbt-tooltip-fade-in .12s ease-out}.gbt-tooltip__bubble.gbt-tooltip__bubble--leaving{animation:gbt-tooltip-fade-out .12s ease-in forwards}@keyframes gbt-tooltip-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-tooltip-fade-out{0%{opacity:1}to{opacity:0}}\n"] }]
4433
+ }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
4434
+
4435
+ let nextId$4 = 0;
4436
+ class RadioGroup {
4437
+ id = input(`gbt-radio-group-${++nextId$4}`, /* @ts-ignore */
4438
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4439
+ label = input.required(/* @ts-ignore */
4440
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4441
+ options = input.required(/* @ts-ignore */
4442
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
4443
+ orientation = input('vertical', /* @ts-ignore */
4444
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
4445
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4446
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4447
+ errorMessage = input(null, /* @ts-ignore */
4448
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
4449
+ selected = signal(null, /* @ts-ignore */
4450
+ ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
4451
+ formDisabled = signal(false, /* @ts-ignore */
4452
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
4453
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
4454
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4455
+ onChange = () => { };
4456
+ onTouched = () => { };
4457
+ writeValue(value) {
4458
+ this.selected.set(value);
4459
+ }
4460
+ registerOnChange(fn) {
4461
+ this.onChange = fn;
4462
+ }
4463
+ registerOnTouched(fn) {
4464
+ this.onTouched = fn;
4465
+ }
4466
+ setDisabledState(isDisabled) {
4467
+ this.formDisabled.set(isDisabled);
4468
+ }
4469
+ isSelected(value) {
4470
+ return this.selected() === value;
4471
+ }
4472
+ selectOption(value) {
4473
+ this.selected.set(value);
4474
+ this.onChange(value);
4475
+ this.onTouched();
4476
+ }
4477
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
4478
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RadioGroup, isStandalone: true, selector: "gbt-radio-group", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", 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 } }, providers: [
4479
+ {
4480
+ provide: NG_VALUE_ACCESSOR,
4481
+ useExisting: forwardRef(() => RadioGroup),
4482
+ multi: true,
4483
+ },
4484
+ ], ngImport: i0, template: "<fieldset\n class=\"gbt-radio-group\"\n [attr.data-orientation]=\"orientation()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n>\n <legend class=\"gbt-radio-group__legend\">{{ label() }}{{ required() ? ' *' : '' }}</legend>\n <div class=\"gbt-radio-group__options\">\n @for (option of options(); track option.value; let i = $index) {\n <label class=\"gbt-radio-group__option\">\n <input\n type=\"radio\"\n [id]=\"id() + '-' + i\"\n [name]=\"id()\"\n [value]=\"option.value\"\n [checked]=\"isSelected(option.value)\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"selectOption(option.value)\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-radio-group__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</fieldset>\n", styles: [".gbt-radio-group{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;border:none}.gbt-radio-group:disabled,.gbt-radio-group[disabled]{opacity:.5}.gbt-radio-group__legend{padding:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-radio-group__options{display:flex;flex-direction:column;gap:.5rem}.gbt-radio-group[data-orientation=horizontal] .gbt-radio-group__options{flex-direction:row;flex-wrap:wrap;gap:1.25rem}.gbt-radio-group__option{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-radio-group__option:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-radio-group__option:has(input:disabled){cursor:not-allowed;opacity:.5}.gbt-radio-group__option input{width:1rem;height:1rem;accent-color:var(--primary)}.gbt-radio-group__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4485
+ }
4486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RadioGroup, decorators: [{
4487
+ type: Component,
4488
+ args: [{ selector: 'gbt-radio-group', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
4489
+ {
4490
+ provide: NG_VALUE_ACCESSOR,
4491
+ useExisting: forwardRef(() => RadioGroup),
4492
+ multi: true,
4493
+ },
4494
+ ], template: "<fieldset\n class=\"gbt-radio-group\"\n [attr.data-orientation]=\"orientation()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n>\n <legend class=\"gbt-radio-group__legend\">{{ label() }}{{ required() ? ' *' : '' }}</legend>\n <div class=\"gbt-radio-group__options\">\n @for (option of options(); track option.value; let i = $index) {\n <label class=\"gbt-radio-group__option\">\n <input\n type=\"radio\"\n [id]=\"id() + '-' + i\"\n [name]=\"id()\"\n [value]=\"option.value\"\n [checked]=\"isSelected(option.value)\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"selectOption(option.value)\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-radio-group__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</fieldset>\n", styles: [".gbt-radio-group{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;border:none}.gbt-radio-group:disabled,.gbt-radio-group[disabled]{opacity:.5}.gbt-radio-group__legend{padding:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-radio-group__options{display:flex;flex-direction:column;gap:.5rem}.gbt-radio-group[data-orientation=horizontal] .gbt-radio-group__options{flex-direction:row;flex-wrap:wrap;gap:1.25rem}.gbt-radio-group__option{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-radio-group__option:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-radio-group__option:has(input:disabled){cursor:not-allowed;opacity:.5}.gbt-radio-group__option input{width:1rem;height:1rem;accent-color:var(--primary)}.gbt-radio-group__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
4495
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", 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 }] }] } });
4496
+
4497
+ let nextSwitchId = 0;
4498
+ class Switch {
4499
+ id = input(`gbt-switch-${++nextSwitchId}`, /* @ts-ignore */
4500
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4501
+ label = input('', /* @ts-ignore */
4502
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4503
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4504
+ checked = signal(false, /* @ts-ignore */
4505
+ ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
4506
+ formDisabled = signal(false, /* @ts-ignore */
4507
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
4508
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
4509
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4510
+ onChange = () => { };
4511
+ onTouched = () => { };
4512
+ writeValue(value) {
4513
+ this.checked.set(!!value);
4514
+ }
4515
+ registerOnChange(fn) {
4516
+ this.onChange = fn;
4517
+ }
4518
+ registerOnTouched(fn) {
4519
+ this.onTouched = fn;
2957
4520
  }
2958
- show() {
2959
- if (this.hideTimer !== null) {
2960
- clearTimeout(this.hideTimer);
2961
- this.hideTimer = null;
4521
+ setDisabledState(isDisabled) {
4522
+ this.formDisabled.set(isDisabled);
4523
+ }
4524
+ onToggle(event) {
4525
+ const value = event.target.checked;
4526
+ this.checked.set(value);
4527
+ this.onChange(value);
4528
+ this.onTouched();
4529
+ }
4530
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Switch, deps: [], target: i0.ɵɵFactoryTarget.Component });
4531
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: Switch, isStandalone: true, selector: "gbt-switch", 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: [
4532
+ {
4533
+ provide: NG_VALUE_ACCESSOR,
4534
+ useExisting: forwardRef(() => Switch),
4535
+ multi: true,
4536
+ },
4537
+ ], ngImport: i0, template: "<label class=\"gbt-switch\" [class.gbt-switch--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"gbt-switch__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span class=\"gbt-switch__track\">\n <span class=\"gbt-switch__thumb\"></span>\n </span>\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-switch{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-switch:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-switch--disabled{cursor:not-allowed;opacity:.5}.gbt-switch__input{position:absolute;width:2.25rem;height:1.25rem;margin:0;opacity:0;cursor:inherit}.gbt-switch__track{position:relative;display:inline-flex;flex-shrink:0;align-items:center;width:2.25rem;height:1.25rem;background:var(--border-color);border-radius:999px;transition:background .15s ease}.gbt-switch__input:checked+.gbt-switch__track{background:var(--primary)}.gbt-switch__input:focus-visible+.gbt-switch__track{outline:2px solid var(--primary);outline-offset:2px}.gbt-switch__thumb{position:absolute;top:.125rem;left:.125rem;width:1rem;height:1rem;background:var(--bg-principal);border-radius:50%;box-shadow:var(--site-shadow-sm);transition:transform .15s ease}.gbt-switch__input:checked~.gbt-switch__track .gbt-switch__thumb{transform:translate(1rem)}@media(prefers-reduced-motion:reduce){.gbt-switch__track,.gbt-switch__thumb{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4538
+ }
4539
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Switch, decorators: [{
4540
+ type: Component,
4541
+ args: [{ selector: 'gbt-switch', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
4542
+ {
4543
+ provide: NG_VALUE_ACCESSOR,
4544
+ useExisting: forwardRef(() => Switch),
4545
+ multi: true,
4546
+ },
4547
+ ], template: "<label class=\"gbt-switch\" [class.gbt-switch--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"gbt-switch__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span class=\"gbt-switch__track\">\n <span class=\"gbt-switch__thumb\"></span>\n </span>\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-switch{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-switch:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-switch--disabled{cursor:not-allowed;opacity:.5}.gbt-switch__input{position:absolute;width:2.25rem;height:1.25rem;margin:0;opacity:0;cursor:inherit}.gbt-switch__track{position:relative;display:inline-flex;flex-shrink:0;align-items:center;width:2.25rem;height:1.25rem;background:var(--border-color);border-radius:999px;transition:background .15s ease}.gbt-switch__input:checked+.gbt-switch__track{background:var(--primary)}.gbt-switch__input:focus-visible+.gbt-switch__track{outline:2px solid var(--primary);outline-offset:2px}.gbt-switch__thumb{position:absolute;top:.125rem;left:.125rem;width:1rem;height:1rem;background:var(--bg-principal);border-radius:50%;box-shadow:var(--site-shadow-sm);transition:transform .15s ease}.gbt-switch__input:checked~.gbt-switch__track .gbt-switch__thumb{transform:translate(1rem)}@media(prefers-reduced-motion:reduce){.gbt-switch__track,.gbt-switch__thumb{transition:none}}\n"] }]
4548
+ }], 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 }] }] } });
4549
+
4550
+ let nextId$3 = 0;
4551
+ class Textarea {
4552
+ id = input(`gbt-textarea-${++nextId$3}`, /* @ts-ignore */
4553
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4554
+ label = input('', /* @ts-ignore */
4555
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4556
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4557
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4558
+ placeholder = input('', /* @ts-ignore */
4559
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4560
+ errorMessage = input(null, /* @ts-ignore */
4561
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
4562
+ rows = input(3, /* @ts-ignore */
4563
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
4564
+ committed = output();
4565
+ value = signal('', /* @ts-ignore */
4566
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4567
+ formDisabled = signal(false, /* @ts-ignore */
4568
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
4569
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
4570
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4571
+ onChange = () => { };
4572
+ onTouched = () => { };
4573
+ writeValue(value) {
4574
+ this.value.set(value ?? '');
4575
+ }
4576
+ registerOnChange(fn) {
4577
+ this.onChange = fn;
4578
+ }
4579
+ registerOnTouched(fn) {
4580
+ this.onTouched = fn;
4581
+ }
4582
+ setDisabledState(isDisabled) {
4583
+ this.formDisabled.set(isDisabled);
4584
+ }
4585
+ onInput(event) {
4586
+ const value = event.target.value;
4587
+ this.value.set(value);
4588
+ this.onChange(value);
4589
+ }
4590
+ onBlur() {
4591
+ this.onTouched();
4592
+ this.committed.emit(this.value());
4593
+ }
4594
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Textarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
4595
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Textarea, isStandalone: true, selector: "gbt-textarea", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { committed: "committed" }, providers: [
4596
+ {
4597
+ provide: NG_VALUE_ACCESSOR,
4598
+ useExisting: forwardRef(() => Textarea),
4599
+ multi: true,
4600
+ },
4601
+ ], ngImport: i0, 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"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4602
+ }
4603
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Textarea, decorators: [{
4604
+ type: Component,
4605
+ args: [{ selector: 'gbt-textarea', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
4606
+ {
4607
+ provide: NG_VALUE_ACCESSOR,
4608
+ useExisting: forwardRef(() => Textarea),
4609
+ multi: true,
4610
+ },
4611
+ ], 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"] }]
4612
+ }], 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"] }] } });
4613
+
4614
+ let nextAutocompleteId = 0;
4615
+ class Autocomplete {
4616
+ elementRef = inject(ElementRef);
4617
+ id = input(`gbt-autocomplete-${++nextAutocompleteId}`, /* @ts-ignore */
4618
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4619
+ label = input('', /* @ts-ignore */
4620
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4621
+ placeholder = input('', /* @ts-ignore */
4622
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4623
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4624
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4625
+ errorMessage = input(null, /* @ts-ignore */
4626
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
4627
+ search = input.required(/* @ts-ignore */
4628
+ ...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
4629
+ displayFn = input((item) => String(item), /* @ts-ignore */
4630
+ ...(ngDevMode ? [{ debugName: "displayFn" }] : /* istanbul ignore next */ []));
4631
+ itemTemplate = input(/* @ts-ignore */
4632
+ ...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
4633
+ debounceMs = input(300, /* @ts-ignore */
4634
+ ...(ngDevMode ? [{ debugName: "debounceMs" }] : /* istanbul ignore next */ []));
4635
+ minLength = input(1, /* @ts-ignore */
4636
+ ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
4637
+ loadingMessage = input('Searching…', /* @ts-ignore */
4638
+ ...(ngDevMode ? [{ debugName: "loadingMessage" }] : /* istanbul ignore next */ []));
4639
+ noResultsMessage = input('No results', /* @ts-ignore */
4640
+ ...(ngDevMode ? [{ debugName: "noResultsMessage" }] : /* istanbul ignore next */ []));
4641
+ searchErrorMessage = input('Search failed', /* @ts-ignore */
4642
+ ...(ngDevMode ? [{ debugName: "searchErrorMessage" }] : /* istanbul ignore next */ []));
4643
+ resultsAnnouncement = input((count) => `${count} result${count !== 1 ? 's' : ''}`, /* @ts-ignore */
4644
+ ...(ngDevMode ? [{ debugName: "resultsAnnouncement" }] : /* istanbul ignore next */ []));
4645
+ itemSelected = output();
4646
+ query = signal('', /* @ts-ignore */
4647
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
4648
+ open = signal(false, /* @ts-ignore */
4649
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
4650
+ results = signal([], /* @ts-ignore */
4651
+ ...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
4652
+ loading = signal(false, /* @ts-ignore */
4653
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
4654
+ searchFailed = signal(false, /* @ts-ignore */
4655
+ ...(ngDevMode ? [{ debugName: "searchFailed" }] : /* istanbul ignore next */ []));
4656
+ activeIndex = signal(0, /* @ts-ignore */
4657
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
4658
+ selectedItem = signal(null, /* @ts-ignore */
4659
+ ...(ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []));
4660
+ panelStyle = signal(null, /* @ts-ignore */
4661
+ ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
4662
+ formDisabled = signal(false, /* @ts-ignore */
4663
+ ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
4664
+ isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
4665
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4666
+ hasNoResults = computed(() => this.open() && !this.loading() && !this.searchFailed() && this.results().length === 0, /* @ts-ignore */
4667
+ ...(ngDevMode ? [{ debugName: "hasNoResults" }] : /* istanbul ignore next */ []));
4668
+ activeOptionId = computed(() => this.open() && this.results().length > 0 ? `${this.id()}-option-${this.activeIndex()}` : null, /* @ts-ignore */
4669
+ ...(ngDevMode ? [{ debugName: "activeOptionId" }] : /* istanbul ignore next */ []));
4670
+ onChange = () => { };
4671
+ onTouched = () => { };
4672
+ requestSeq = 0;
4673
+ debounceHandle;
4674
+ subscription;
4675
+ setDisabledState(isDisabled) {
4676
+ this.formDisabled.set(isDisabled);
4677
+ }
4678
+ writeValue(value) {
4679
+ this.selectedItem.set(value);
4680
+ this.query.set(value === null || value === undefined ? '' : this.displayFn()(value));
4681
+ }
4682
+ registerOnChange(fn) {
4683
+ this.onChange = fn;
4684
+ }
4685
+ registerOnTouched(fn) {
4686
+ this.onTouched = fn;
4687
+ }
4688
+ onInput(event) {
4689
+ const value = event.target.value;
4690
+ this.query.set(value);
4691
+ this.activeIndex.set(0);
4692
+ if (this.selectedItem() !== null) {
4693
+ this.selectedItem.set(null);
4694
+ this.onChange(null);
2962
4695
  }
2963
- this.closing.set(false);
2964
- this.updatePosition();
2965
- this.visible.set(true);
4696
+ this.scheduleSearch(value);
2966
4697
  }
2967
- updatePosition() {
2968
- const rect = this.elementRef.nativeElement.getBoundingClientRect();
2969
- switch (this.position()) {
2970
- case 'top':
2971
- this.coords.set({ top: rect.top - GAP_PX, left: rect.left + rect.width / 2 });
2972
- break;
2973
- case 'bottom':
2974
- this.coords.set({ top: rect.bottom + GAP_PX, left: rect.left + rect.width / 2 });
2975
- break;
2976
- case 'left':
2977
- this.coords.set({ top: rect.top + rect.height / 2, left: rect.left - GAP_PX });
2978
- break;
2979
- case 'right':
2980
- this.coords.set({ top: rect.top + rect.height / 2, left: rect.right + GAP_PX });
2981
- break;
4698
+ onFocus() {
4699
+ if (this.query().trim().length >= this.minLength() &&
4700
+ (this.results().length > 0 || this.searchFailed())) {
4701
+ this.open.set(true);
4702
+ this.updatePanelPosition();
2982
4703
  }
2983
4704
  }
2984
- hide() {
2985
- if (this.showTimer !== null) {
2986
- clearTimeout(this.showTimer);
2987
- this.showTimer = null;
4705
+ onBlur() {
4706
+ this.onTouched();
4707
+ setTimeout(() => {
4708
+ if (!this.elementRef.nativeElement.contains(document.activeElement)) {
4709
+ this.open.set(false);
4710
+ }
4711
+ }, 200);
4712
+ }
4713
+ scheduleSearch(value) {
4714
+ clearTimeout(this.debounceHandle);
4715
+ if (value.trim().length < this.minLength()) {
4716
+ this.requestSeq++;
4717
+ this.subscription?.unsubscribe();
4718
+ this.open.set(false);
4719
+ this.results.set([]);
4720
+ this.loading.set(false);
4721
+ this.searchFailed.set(false);
4722
+ return;
4723
+ }
4724
+ this.debounceHandle = setTimeout(() => this.runSearch(value), this.debounceMs());
4725
+ }
4726
+ runSearch(query) {
4727
+ const seq = ++this.requestSeq;
4728
+ this.subscription?.unsubscribe();
4729
+ this.loading.set(true);
4730
+ this.searchFailed.set(false);
4731
+ this.open.set(true);
4732
+ this.updatePanelPosition();
4733
+ const applyResults = (items) => {
4734
+ if (seq !== this.requestSeq)
4735
+ return;
4736
+ this.results.set(items);
4737
+ this.loading.set(false);
4738
+ this.activeIndex.set(0);
4739
+ this.updatePanelPosition();
4740
+ };
4741
+ const applyError = () => {
4742
+ if (seq !== this.requestSeq)
4743
+ return;
4744
+ this.results.set([]);
4745
+ this.loading.set(false);
4746
+ this.searchFailed.set(true);
4747
+ this.updatePanelPosition();
4748
+ };
4749
+ const result = this.search()(query);
4750
+ if (isObservable(result)) {
4751
+ this.subscription = result.subscribe({ next: applyResults, error: applyError });
4752
+ }
4753
+ else {
4754
+ result.then(applyResults, applyError);
2988
4755
  }
2989
- if (!this.visible() || this.closing())
2990
- return;
2991
- this.closing.set(true);
2992
- this.hideTimer = setTimeout(() => {
2993
- this.hideTimer = null;
2994
- this.closing.set(false);
2995
- this.visible.set(false);
2996
- }, FADE_MS);
2997
4756
  }
2998
- ngOnDestroy() {
2999
- if (this.showTimer !== null) {
3000
- clearTimeout(this.showTimer);
3001
- this.showTimer = null;
4757
+ updatePanelPosition() {
4758
+ if (!this.open()) {
4759
+ return;
3002
4760
  }
3003
- if (this.hideTimer !== null) {
3004
- clearTimeout(this.hideTimer);
3005
- this.hideTimer = null;
4761
+ const trigger = this.elementRef.nativeElement.querySelector('.gbt-autocomplete__input');
4762
+ if (!trigger) {
4763
+ return;
3006
4764
  }
4765
+ const rect = trigger.getBoundingClientRect();
4766
+ this.panelStyle.set({
4767
+ top: `${rect.bottom + 6}px`,
4768
+ left: `${rect.left}px`,
4769
+ width: `${rect.width}px`,
4770
+ });
3007
4771
  }
3008
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tooltip, deps: [], target: i0.ɵɵFactoryTarget.Component });
3009
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Tooltip, isStandalone: true, selector: "gbt-tooltip", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "hide()", "focusin": "onFocusIn()", "focusout": "hide()", "keydown.escape": "hide()", "window:scroll": "updatePosition()", "window:resize": "updatePosition()" }, classAttribute: "gbt-tooltip-host" }, exportAs: ["gbtTooltip"], ngImport: i0, template: "<ng-content />\n@if (visible() && coords(); as pos) {\n <span\n class=\"gbt-tooltip__bubble\"\n [class.gbt-tooltip__bubble--leaving]=\"closing()\"\n role=\"tooltip\"\n [id]=\"tooltipId\"\n [attr.data-position]=\"position()\"\n [style.top.px]=\"pos.top\"\n [style.left.px]=\"pos.left\"\n >\n {{ text() }}\n </span>\n}", styles: [".gbt-tooltip-host{display:inline-block}.gbt-tooltip__bubble{position:fixed;z-index:1100;max-width:240px;padding:.375rem .625rem;background:var(--bg-inverse);color:var(--text-on-color);text-align:center;white-space:normal;border:1px solid rgba(255,255,255,.15);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-md);font-size:.8125rem;line-height:1.3;pointer-events:none}.gbt-tooltip__bubble[data-position=top]{transform:translate(-50%,-100%)}.gbt-tooltip__bubble[data-position=bottom]{transform:translate(-50%)}.gbt-tooltip__bubble[data-position=left]{transform:translate(-100%,-50%)}.gbt-tooltip__bubble[data-position=right]{transform:translateY(-50%)}.gbt-tooltip__bubble{animation:gbt-tooltip-fade-in .12s ease-out}.gbt-tooltip__bubble.gbt-tooltip__bubble--leaving{animation:gbt-tooltip-fade-out .12s ease-in forwards}@keyframes gbt-tooltip-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-tooltip-fade-out{0%{opacity:1}to{opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3010
- }
3011
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tooltip, decorators: [{
3012
- type: Component,
3013
- args: [{ selector: 'gbt-tooltip', standalone: true, exportAs: 'gbtTooltip', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3014
- class: 'gbt-tooltip-host',
3015
- '(mouseenter)': 'onMouseEnter()',
3016
- '(mouseleave)': 'hide()',
3017
- '(focusin)': 'onFocusIn()',
3018
- '(focusout)': 'hide()',
3019
- '(keydown.escape)': 'hide()',
3020
- '(window:scroll)': 'updatePosition()',
3021
- '(window:resize)': 'updatePosition()',
3022
- }, template: "<ng-content />\n@if (visible() && coords(); as pos) {\n <span\n class=\"gbt-tooltip__bubble\"\n [class.gbt-tooltip__bubble--leaving]=\"closing()\"\n role=\"tooltip\"\n [id]=\"tooltipId\"\n [attr.data-position]=\"position()\"\n [style.top.px]=\"pos.top\"\n [style.left.px]=\"pos.left\"\n >\n {{ text() }}\n </span>\n}", styles: [".gbt-tooltip-host{display:inline-block}.gbt-tooltip__bubble{position:fixed;z-index:1100;max-width:240px;padding:.375rem .625rem;background:var(--bg-inverse);color:var(--text-on-color);text-align:center;white-space:normal;border:1px solid rgba(255,255,255,.15);border-radius:var(--site-border-radius-sm);box-shadow:var(--site-shadow-md);font-size:.8125rem;line-height:1.3;pointer-events:none}.gbt-tooltip__bubble[data-position=top]{transform:translate(-50%,-100%)}.gbt-tooltip__bubble[data-position=bottom]{transform:translate(-50%)}.gbt-tooltip__bubble[data-position=left]{transform:translate(-100%,-50%)}.gbt-tooltip__bubble[data-position=right]{transform:translateY(-50%)}.gbt-tooltip__bubble{animation:gbt-tooltip-fade-in .12s ease-out}.gbt-tooltip__bubble.gbt-tooltip__bubble--leaving{animation:gbt-tooltip-fade-out .12s ease-in forwards}@keyframes gbt-tooltip-fade-in{0%{opacity:0}to{opacity:1}}@keyframes gbt-tooltip-fade-out{0%{opacity:1}to{opacity:0}}\n"] }]
3023
- }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
3024
-
3025
- let nextId$1 = 0;
3026
- class RadioGroup {
3027
- id = input(`gbt-radio-group-${++nextId$1}`, /* @ts-ignore */
3028
- ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3029
- label = input.required(/* @ts-ignore */
3030
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3031
- options = input.required(/* @ts-ignore */
3032
- ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3033
- orientation = input('vertical', /* @ts-ignore */
3034
- ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
3035
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3036
- required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3037
- errorMessage = input(null, /* @ts-ignore */
3038
- ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3039
- selected = signal(null, /* @ts-ignore */
3040
- ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
3041
- formDisabled = signal(false, /* @ts-ignore */
3042
- ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3043
- isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3044
- ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
3045
- onChange = () => { };
3046
- onTouched = () => { };
3047
- writeValue(value) {
3048
- this.selected.set(value);
3049
- }
3050
- registerOnChange(fn) {
3051
- this.onChange = fn;
3052
- }
3053
- registerOnTouched(fn) {
3054
- this.onTouched = fn;
3055
- }
3056
- setDisabledState(isDisabled) {
3057
- this.formDisabled.set(isDisabled);
4772
+ selectOption(item) {
4773
+ this.selectedItem.set(item);
4774
+ this.query.set(this.displayFn()(item));
4775
+ this.results.set([]);
4776
+ this.open.set(false);
4777
+ this.onChange(item);
4778
+ this.onTouched();
4779
+ this.itemSelected.emit(item);
3058
4780
  }
3059
- isSelected(value) {
3060
- return this.selected() === value;
4781
+ onKeydown(event) {
4782
+ if (this.isDisabled()) {
4783
+ return;
4784
+ }
4785
+ if (event.key === 'Escape') {
4786
+ if (this.open()) {
4787
+ event.preventDefault();
4788
+ event.stopPropagation();
4789
+ this.open.set(false);
4790
+ }
4791
+ return;
4792
+ }
4793
+ if (!this.open() || this.results().length === 0) {
4794
+ return;
4795
+ }
4796
+ const results = this.results();
4797
+ switch (event.key) {
4798
+ case 'ArrowDown':
4799
+ event.preventDefault();
4800
+ this.activeIndex.update((i) => Math.min(i + 1, results.length - 1));
4801
+ break;
4802
+ case 'ArrowUp':
4803
+ event.preventDefault();
4804
+ this.activeIndex.update((i) => Math.max(i - 1, 0));
4805
+ break;
4806
+ case 'Enter': {
4807
+ event.preventDefault();
4808
+ const active = results[this.activeIndex()];
4809
+ if (active) {
4810
+ this.selectOption(active);
4811
+ }
4812
+ break;
4813
+ }
4814
+ }
3061
4815
  }
3062
- selectOption(value) {
3063
- this.selected.set(value);
3064
- this.onChange(value);
3065
- this.onTouched();
4816
+ ngOnDestroy() {
4817
+ clearTimeout(this.debounceHandle);
4818
+ this.subscription?.unsubscribe();
3066
4819
  }
3067
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
3068
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RadioGroup, isStandalone: true, selector: "gbt-radio-group", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", 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 } }, providers: [
4820
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Autocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
4821
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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: [
3069
4822
  {
3070
4823
  provide: NG_VALUE_ACCESSOR,
3071
- useExisting: forwardRef(() => RadioGroup),
4824
+ useExisting: forwardRef(() => Autocomplete),
3072
4825
  multi: true,
3073
4826
  },
3074
- ], ngImport: i0, template: "<fieldset\n class=\"gbt-radio-group\"\n [attr.data-orientation]=\"orientation()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n>\n <legend class=\"gbt-radio-group__legend\">{{ label() }}{{ required() ? ' *' : '' }}</legend>\n <div class=\"gbt-radio-group__options\">\n @for (option of options(); track option.value; let i = $index) {\n <label class=\"gbt-radio-group__option\">\n <input\n type=\"radio\"\n [id]=\"id() + '-' + i\"\n [name]=\"id()\"\n [value]=\"option.value\"\n [checked]=\"isSelected(option.value)\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"selectOption(option.value)\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-radio-group__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</fieldset>\n", styles: [".gbt-radio-group{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;border:none}.gbt-radio-group:disabled,.gbt-radio-group[disabled]{opacity:.5}.gbt-radio-group__legend{padding:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-radio-group__options{display:flex;flex-direction:column;gap:.5rem}.gbt-radio-group[data-orientation=horizontal] .gbt-radio-group__options{flex-direction:row;flex-wrap:wrap;gap:1.25rem}.gbt-radio-group__option{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-radio-group__option:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-radio-group__option:has(input:disabled){cursor:not-allowed;opacity:.5}.gbt-radio-group__option input{width:1rem;height:1rem;accent-color:var(--primary)}.gbt-radio-group__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4827
+ ], 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 });
3075
4828
  }
3076
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RadioGroup, decorators: [{
4829
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Autocomplete, decorators: [{
3077
4830
  type: Component,
3078
- args: [{ selector: 'gbt-radio-group', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
4831
+ args: [{ selector: 'gbt-autocomplete', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
4832
+ '(window:scroll)': 'updatePanelPosition()',
4833
+ '(window:resize)': 'updatePanelPosition()',
4834
+ }, providers: [
3079
4835
  {
3080
4836
  provide: NG_VALUE_ACCESSOR,
3081
- useExisting: forwardRef(() => RadioGroup),
4837
+ useExisting: forwardRef(() => Autocomplete),
3082
4838
  multi: true,
3083
4839
  },
3084
- ], template: "<fieldset\n class=\"gbt-radio-group\"\n [attr.data-orientation]=\"orientation()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n>\n <legend class=\"gbt-radio-group__legend\">{{ label() }}{{ required() ? ' *' : '' }}</legend>\n <div class=\"gbt-radio-group__options\">\n @for (option of options(); track option.value; let i = $index) {\n <label class=\"gbt-radio-group__option\">\n <input\n type=\"radio\"\n [id]=\"id() + '-' + i\"\n [name]=\"id()\"\n [value]=\"option.value\"\n [checked]=\"isSelected(option.value)\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"selectOption(option.value)\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-radio-group__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</fieldset>\n", styles: [".gbt-radio-group{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;border:none}.gbt-radio-group:disabled,.gbt-radio-group[disabled]{opacity:.5}.gbt-radio-group__legend{padding:0;font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-radio-group__options{display:flex;flex-direction:column;gap:.5rem}.gbt-radio-group[data-orientation=horizontal] .gbt-radio-group__options{flex-direction:row;flex-wrap:wrap;gap:1.25rem}.gbt-radio-group__option{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-radio-group__option:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-radio-group__option:has(input:disabled){cursor:not-allowed;opacity:.5}.gbt-radio-group__option input{width:1rem;height:1rem;accent-color:var(--primary)}.gbt-radio-group__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
3085
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", 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 }] }] } });
4840
+ ], 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"] }]
4841
+ }], 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"] }] } });
3086
4842
 
3087
- let nextSwitchId = 0;
3088
- class Switch {
3089
- id = input(`gbt-switch-${++nextSwitchId}`, /* @ts-ignore */
3090
- ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4843
+ class Divider {
4844
+ orientation = input('horizontal', /* @ts-ignore */
4845
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
3091
4846
  label = input('', /* @ts-ignore */
3092
4847
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4848
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Divider, deps: [], target: i0.ɵɵFactoryTarget.Component });
4849
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Divider, isStandalone: true, selector: "gbt-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "attr.data-orientation": "orientation()", "attr.aria-orientation": "orientation() === 'vertical' ? 'vertical' : null" } }, ngImport: i0, template: "@if (label()) {\n <span class=\"gbt-divider__line\"></span>\n <span class=\"gbt-divider__label\">{{ label() }}</span>\n <span class=\"gbt-divider__line\"></span>\n} @else {\n <span class=\"gbt-divider__line\"></span>\n}\n", styles: [":host{display:flex;align-items:center;gap:.75rem}:host[data-orientation=vertical]{flex-direction:column;align-self:stretch}.gbt-divider__line{flex:1;background:var(--border-color)}:host[data-orientation=horizontal] .gbt-divider__line{height:1px}:host[data-orientation=vertical] .gbt-divider__line{width:1px}.gbt-divider__label{flex-shrink:0;font-size:.75rem;font-weight:600;color:var(--text-secondary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4850
+ }
4851
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Divider, decorators: [{
4852
+ type: Component,
4853
+ args: [{ selector: 'gbt-divider', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
4854
+ role: 'separator',
4855
+ '[attr.data-orientation]': 'orientation()',
4856
+ '[attr.aria-orientation]': "orientation() === 'vertical' ? 'vertical' : null",
4857
+ }, template: "@if (label()) {\n <span class=\"gbt-divider__line\"></span>\n <span class=\"gbt-divider__label\">{{ label() }}</span>\n <span class=\"gbt-divider__line\"></span>\n} @else {\n <span class=\"gbt-divider__line\"></span>\n}\n", styles: [":host{display:flex;align-items:center;gap:.75rem}:host[data-orientation=vertical]{flex-direction:column;align-self:stretch}.gbt-divider__line{flex:1;background:var(--border-color)}:host[data-orientation=horizontal] .gbt-divider__line{height:1px}:host[data-orientation=vertical] .gbt-divider__line{width:1px}.gbt-divider__label{flex-shrink:0;font-size:.75rem;font-weight:600;color:var(--text-secondary)}\n"] }]
4858
+ }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
4859
+
4860
+ class Spinner {
4861
+ size = input('md', /* @ts-ignore */
4862
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4863
+ label = input('Loading…', /* @ts-ignore */
4864
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4865
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Spinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
4866
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: Spinner, isStandalone: true, selector: "gbt-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "attr.data-size": "size()" } }, ngImport: i0, template: "<span class=\"gbt-spinner__ring\" aria-hidden=\"true\"></span>\n<span class=\"sr-only\">{{ label() }}</span>\n", styles: [":host{display:inline-flex;color:var(--primary)}:host[data-size=sm]{width:16px;height:16px}:host[data-size=md]{width:24px;height:24px}:host[data-size=lg]{width:40px;height:40px}.gbt-spinner__ring{position:relative;display:block;box-sizing:border-box;width:100%;height:100%;border-radius:50%}.gbt-spinner__ring:before,.gbt-spinner__ring:after{content:\"\";position:absolute;inset:0;box-sizing:border-box;border-radius:50%;border:2px solid currentColor}.gbt-spinner__ring:before{opacity:.15}.gbt-spinner__ring:after{border-color:currentColor transparent transparent transparent;animation:gbt-spinner-spin .6s linear infinite}@media(prefers-reduced-motion:reduce){.gbt-spinner__ring:after{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-spinner-spin{to{transform:rotate(360deg)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4867
+ }
4868
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Spinner, decorators: [{
4869
+ type: Component,
4870
+ args: [{ selector: 'gbt-spinner', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
4871
+ role: 'status',
4872
+ '[attr.data-size]': 'size()',
4873
+ }, template: "<span class=\"gbt-spinner__ring\" aria-hidden=\"true\"></span>\n<span class=\"sr-only\">{{ label() }}</span>\n", styles: [":host{display:inline-flex;color:var(--primary)}:host[data-size=sm]{width:16px;height:16px}:host[data-size=md]{width:24px;height:24px}:host[data-size=lg]{width:40px;height:40px}.gbt-spinner__ring{position:relative;display:block;box-sizing:border-box;width:100%;height:100%;border-radius:50%}.gbt-spinner__ring:before,.gbt-spinner__ring:after{content:\"\";position:absolute;inset:0;box-sizing:border-box;border-radius:50%;border:2px solid currentColor}.gbt-spinner__ring:before{opacity:.15}.gbt-spinner__ring:after{border-color:currentColor transparent transparent transparent;animation:gbt-spinner-spin .6s linear infinite}@media(prefers-reduced-motion:reduce){.gbt-spinner__ring:after{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-spinner-spin{to{transform:rotate(360deg)}}\n"] }]
4874
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
4875
+
4876
+ let nextId$2 = 0;
4877
+ class Slider {
4878
+ id = input(`gbt-slider-${++nextId$2}`, /* @ts-ignore */
4879
+ ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4880
+ label = input.required(/* @ts-ignore */
4881
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4882
+ min = input(0, /* @ts-ignore */
4883
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
4884
+ max = input(100, /* @ts-ignore */
4885
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
4886
+ step = input(1, /* @ts-ignore */
4887
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
3093
4888
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3094
- checked = signal(false, /* @ts-ignore */
3095
- ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
4889
+ errorMessage = input(null, /* @ts-ignore */
4890
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
4891
+ showValue = input(true, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4892
+ formatValue = input((value) => `${value}`, /* @ts-ignore */
4893
+ ...(ngDevMode ? [{ debugName: "formatValue" }] : /* istanbul ignore next */ []));
4894
+ value = signal(0, /* @ts-ignore */
4895
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3096
4896
  formDisabled = signal(false, /* @ts-ignore */
3097
4897
  ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3098
4898
  isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3099
4899
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4900
+ fillPercent = computed(() => {
4901
+ const range = this.max() - this.min();
4902
+ if (range <= 0) {
4903
+ return 0;
4904
+ }
4905
+ return ((this.value() - this.min()) / range) * 100;
4906
+ }, /* @ts-ignore */
4907
+ ...(ngDevMode ? [{ debugName: "fillPercent" }] : /* istanbul ignore next */ []));
3100
4908
  onChange = () => { };
3101
4909
  onTouched = () => { };
3102
4910
  writeValue(value) {
3103
- this.checked.set(!!value);
4911
+ this.value.set(value ?? 0);
3104
4912
  }
3105
4913
  registerOnChange(fn) {
3106
4914
  this.onChange = fn;
@@ -3111,49 +4919,105 @@ class Switch {
3111
4919
  setDisabledState(isDisabled) {
3112
4920
  this.formDisabled.set(isDisabled);
3113
4921
  }
3114
- onToggle(event) {
3115
- const value = event.target.checked;
3116
- this.checked.set(value);
4922
+ onInput(event) {
4923
+ const value = Number(event.target.value);
4924
+ this.value.set(value);
3117
4925
  this.onChange(value);
4926
+ }
4927
+ onBlur() {
3118
4928
  this.onTouched();
3119
4929
  }
3120
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Switch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3121
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: Switch, isStandalone: true, selector: "gbt-switch", 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: [
4930
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Slider, deps: [], target: i0.ɵɵFactoryTarget.Component });
4931
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Slider, isStandalone: true, selector: "gbt-slider", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, formatValue: { classPropertyName: "formatValue", publicName: "formatValue", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3122
4932
  {
3123
4933
  provide: NG_VALUE_ACCESSOR,
3124
- useExisting: forwardRef(() => Switch),
4934
+ useExisting: forwardRef(() => Slider),
3125
4935
  multi: true,
3126
4936
  },
3127
- ], ngImport: i0, template: "<label class=\"gbt-switch\" [class.gbt-switch--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"gbt-switch__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span class=\"gbt-switch__track\">\n <span class=\"gbt-switch__thumb\"></span>\n </span>\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-switch{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-switch:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-switch--disabled{cursor:not-allowed;opacity:.5}.gbt-switch__input{position:absolute;width:2.25rem;height:1.25rem;margin:0;opacity:0;cursor:inherit}.gbt-switch__track{position:relative;display:inline-flex;flex-shrink:0;align-items:center;width:2.25rem;height:1.25rem;background:var(--border-color);border-radius:999px;transition:background .15s ease}.gbt-switch__input:checked+.gbt-switch__track{background:var(--primary)}.gbt-switch__input:focus-visible+.gbt-switch__track{outline:2px solid var(--primary);outline-offset:2px}.gbt-switch__thumb{position:absolute;top:.125rem;left:.125rem;width:1rem;height:1rem;background:var(--bg-principal);border-radius:50%;box-shadow:var(--site-shadow-sm);transition:transform .15s ease}.gbt-switch__input:checked~.gbt-switch__track .gbt-switch__thumb{transform:translate(1rem)}@media(prefers-reduced-motion:reduce){.gbt-switch__track,.gbt-switch__thumb{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4937
+ ], ngImport: i0, template: "<div class=\"gbt-slider\">\n <div class=\"gbt-slider__header\">\n <label [for]=\"id()\">{{ label() }}</label>\n @if (showValue()) {\n <span class=\"gbt-slider__value\">{{ formatValue()(value()) }}</span>\n }\n </div>\n <input\n type=\"range\"\n [id]=\"id()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [value]=\"value()\"\n [disabled]=\"isDisabled()\"\n [style.--gbt-slider-fill.%]=\"fillPercent()\"\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 (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-slider__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-slider{display:flex;flex-direction:column;gap:.375rem}.gbt-slider label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-slider__header{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem}.gbt-slider__value{font-size:.8125rem;font-weight:600;color:var(--text-primary)}.gbt-slider__error{margin:0;font-size:.75rem;color:var(--color-error-text)}input[type=range]{--gbt-slider-fill: 0;box-sizing:border-box;width:100%;height:20px;padding:0;background:transparent;appearance:none;cursor:pointer}input[type=range]:disabled{cursor:not-allowed;opacity:.5}input[type=range]:focus-visible{outline:none}input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:linear-gradient(to right,var(--primary) 0%,var(--primary) var(--gbt-slider-fill),var(--border-color) var(--gbt-slider-fill),var(--border-color) 100%)}input[type=range]::-webkit-slider-thumb{box-sizing:border-box;width:18px;height:18px;margin-top:-7px;background:var(--bg-principal);border:2px solid var(--primary);border-radius:50%;appearance:none;cursor:pointer}input[type=range]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--primary);outline-offset:2px}input[type=range]::-moz-range-track{height:4px;border-radius:999px;background:var(--border-color)}input[type=range]::-moz-range-progress{height:4px;border-radius:999px;background:var(--primary)}input[type=range]::-moz-range-thumb{box-sizing:border-box;width:18px;height:18px;background:var(--bg-principal);border:2px solid var(--primary);border-radius:50%;cursor:pointer}input[type=range]:focus-visible::-moz-range-thumb{outline:2px solid var(--primary);outline-offset:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3128
4938
  }
3129
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Switch, decorators: [{
4939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Slider, decorators: [{
3130
4940
  type: Component,
3131
- args: [{ selector: 'gbt-switch', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
4941
+ args: [{ selector: 'gbt-slider', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3132
4942
  {
3133
4943
  provide: NG_VALUE_ACCESSOR,
3134
- useExisting: forwardRef(() => Switch),
4944
+ useExisting: forwardRef(() => Slider),
3135
4945
  multi: true,
3136
4946
  },
3137
- ], template: "<label class=\"gbt-switch\" [class.gbt-switch--disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"gbt-switch__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onToggle($event)\"\n />\n <span class=\"gbt-switch__track\">\n <span class=\"gbt-switch__thumb\"></span>\n </span>\n <span>{{ label() }}</span>\n</label>\n", styles: [".gbt-switch{position:relative;display:inline-flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--text-primary);cursor:pointer}.gbt-switch:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-switch--disabled{cursor:not-allowed;opacity:.5}.gbt-switch__input{position:absolute;width:2.25rem;height:1.25rem;margin:0;opacity:0;cursor:inherit}.gbt-switch__track{position:relative;display:inline-flex;flex-shrink:0;align-items:center;width:2.25rem;height:1.25rem;background:var(--border-color);border-radius:999px;transition:background .15s ease}.gbt-switch__input:checked+.gbt-switch__track{background:var(--primary)}.gbt-switch__input:focus-visible+.gbt-switch__track{outline:2px solid var(--primary);outline-offset:2px}.gbt-switch__thumb{position:absolute;top:.125rem;left:.125rem;width:1rem;height:1rem;background:var(--bg-principal);border-radius:50%;box-shadow:var(--site-shadow-sm);transition:transform .15s ease}.gbt-switch__input:checked~.gbt-switch__track .gbt-switch__thumb{transform:translate(1rem)}@media(prefers-reduced-motion:reduce){.gbt-switch__track,.gbt-switch__thumb{transition:none}}\n"] }]
3138
- }], 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 }] }] } });
4947
+ ], template: "<div class=\"gbt-slider\">\n <div class=\"gbt-slider__header\">\n <label [for]=\"id()\">{{ label() }}</label>\n @if (showValue()) {\n <span class=\"gbt-slider__value\">{{ formatValue()(value()) }}</span>\n }\n </div>\n <input\n type=\"range\"\n [id]=\"id()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [value]=\"value()\"\n [disabled]=\"isDisabled()\"\n [style.--gbt-slider-fill.%]=\"fillPercent()\"\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 (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-slider__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-slider{display:flex;flex-direction:column;gap:.375rem}.gbt-slider label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-slider__header{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem}.gbt-slider__value{font-size:.8125rem;font-weight:600;color:var(--text-primary)}.gbt-slider__error{margin:0;font-size:.75rem;color:var(--color-error-text)}input[type=range]{--gbt-slider-fill: 0;box-sizing:border-box;width:100%;height:20px;padding:0;background:transparent;appearance:none;cursor:pointer}input[type=range]:disabled{cursor:not-allowed;opacity:.5}input[type=range]:focus-visible{outline:none}input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:linear-gradient(to right,var(--primary) 0%,var(--primary) var(--gbt-slider-fill),var(--border-color) var(--gbt-slider-fill),var(--border-color) 100%)}input[type=range]::-webkit-slider-thumb{box-sizing:border-box;width:18px;height:18px;margin-top:-7px;background:var(--bg-principal);border:2px solid var(--primary);border-radius:50%;appearance:none;cursor:pointer}input[type=range]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--primary);outline-offset:2px}input[type=range]::-moz-range-track{height:4px;border-radius:999px;background:var(--border-color)}input[type=range]::-moz-range-progress{height:4px;border-radius:999px;background:var(--primary)}input[type=range]::-moz-range-thumb{box-sizing:border-box;width:18px;height:18px;background:var(--bg-principal);border:2px solid var(--primary);border-radius:50%;cursor:pointer}input[type=range]:focus-visible::-moz-range-thumb{outline:2px solid var(--primary);outline-offset:2px}\n"] }]
4948
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], formatValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatValue", required: false }] }] } });
3139
4949
 
3140
- let nextId = 0;
3141
- class Textarea {
3142
- id = input(`gbt-textarea-${++nextId}`, /* @ts-ignore */
4950
+ class Stepper {
4951
+ steps = input.required(/* @ts-ignore */
4952
+ ...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
4953
+ activeIndex = model(0, /* @ts-ignore */
4954
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
4955
+ orientation = input('horizontal', /* @ts-ignore */
4956
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
4957
+ completedLabel = input('Completed', /* @ts-ignore */
4958
+ ...(ngDevMode ? [{ debugName: "completedLabel" }] : /* istanbul ignore next */ []));
4959
+ errorLabel = input('Error', /* @ts-ignore */
4960
+ ...(ngDevMode ? [{ debugName: "errorLabel" }] : /* istanbul ignore next */ []));
4961
+ statusOf(index) {
4962
+ const step = this.steps()[index];
4963
+ const active = this.activeIndex();
4964
+ if (step.hasError && index <= active) {
4965
+ return 'error';
4966
+ }
4967
+ if (index < active) {
4968
+ return 'completed';
4969
+ }
4970
+ if (index === active) {
4971
+ return 'current';
4972
+ }
4973
+ return 'upcoming';
4974
+ }
4975
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Stepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
4976
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Stepper, isStandalone: true, selector: "gbt-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, completedLabel: { classPropertyName: "completedLabel", publicName: "completedLabel", isSignal: true, isRequired: false, transformFunction: null }, errorLabel: { classPropertyName: "errorLabel", publicName: "errorLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, ngImport: i0, template: "<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf($index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ $index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf($index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf($index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n </span>\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4977
+ }
4978
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Stepper, decorators: [{
4979
+ type: Component,
4980
+ args: [{ selector: 'gbt-stepper', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf($index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ $index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf($index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf($index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n </span>\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
4981
+ }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], completedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "completedLabel", required: false }] }], errorLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorLabel", required: false }] }] } });
4982
+
4983
+ let nextId$1 = 0;
4984
+ function formatFileSize(bytes) {
4985
+ if (bytes < 1024) {
4986
+ return `${bytes} B`;
4987
+ }
4988
+ if (bytes < 1024 * 1024) {
4989
+ return `${(bytes / 1024).toFixed(1)} KB`;
4990
+ }
4991
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
4992
+ }
4993
+ class FileUpload {
4994
+ fileInput = viewChild('fileInput', /* @ts-ignore */
4995
+ ...(ngDevMode ? [{ debugName: "fileInput" }] : /* istanbul ignore next */ []));
4996
+ id = input(`gbt-file-upload-${++nextId$1}`, /* @ts-ignore */
3143
4997
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3144
4998
  label = input('', /* @ts-ignore */
3145
4999
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3146
- required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5000
+ multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5001
+ accept = input('', /* @ts-ignore */
5002
+ ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
5003
+ maxSizeMb = input(null, /* @ts-ignore */
5004
+ ...(ngDevMode ? [{ debugName: "maxSizeMb" }] : /* istanbul ignore next */ []));
3147
5005
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3148
- placeholder = input('', /* @ts-ignore */
3149
- ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3150
5006
  errorMessage = input(null, /* @ts-ignore */
3151
5007
  ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3152
- rows = input(3, /* @ts-ignore */
3153
- ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
3154
- committed = output();
3155
- value = signal('', /* @ts-ignore */
3156
- ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5008
+ dropLabel = input('Drag and drop a file here, or click to browse', /* @ts-ignore */
5009
+ ...(ngDevMode ? [{ debugName: "dropLabel" }] : /* istanbul ignore next */ []));
5010
+ removeLabel = input((name) => `Remove ${name}`, /* @ts-ignore */
5011
+ ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
5012
+ oversizeMessage = input((name, maxSizeMb) => `${name} exceeds ${maxSizeMb} MB and was not added.`, /* @ts-ignore */
5013
+ ...(ngDevMode ? [{ debugName: "oversizeMessage" }] : /* istanbul ignore next */ []));
5014
+ files = signal([], /* @ts-ignore */
5015
+ ...(ngDevMode ? [{ debugName: "files" }] : /* istanbul ignore next */ []));
5016
+ rejections = signal([], /* @ts-ignore */
5017
+ ...(ngDevMode ? [{ debugName: "rejections" }] : /* istanbul ignore next */ []));
5018
+ dragOver = signal(false, /* @ts-ignore */
5019
+ ...(ngDevMode ? [{ debugName: "dragOver" }] : /* istanbul ignore next */ []));
5020
+ formatFileSize = formatFileSize;
3157
5021
  formDisabled = signal(false, /* @ts-ignore */
3158
5022
  ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3159
5023
  isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
@@ -3161,7 +5025,7 @@ class Textarea {
3161
5025
  onChange = () => { };
3162
5026
  onTouched = () => { };
3163
5027
  writeValue(value) {
3164
- this.value.set(value ?? '');
5028
+ this.files.set(value ?? []);
3165
5029
  }
3166
5030
  registerOnChange(fn) {
3167
5031
  this.onChange = fn;
@@ -3172,102 +5036,152 @@ class Textarea {
3172
5036
  setDisabledState(isDisabled) {
3173
5037
  this.formDisabled.set(isDisabled);
3174
5038
  }
3175
- onInput(event) {
3176
- const value = event.target.value;
3177
- this.value.set(value);
3178
- this.onChange(value);
5039
+ openPicker() {
5040
+ if (this.isDisabled()) {
5041
+ return;
5042
+ }
5043
+ this.fileInput()?.nativeElement.click();
3179
5044
  }
3180
- onBlur() {
5045
+ onFilesSelected(event) {
5046
+ const input = event.target;
5047
+ this.addFiles(input.files);
5048
+ input.value = '';
5049
+ }
5050
+ onDragEnter(event) {
5051
+ event.preventDefault();
5052
+ if (!this.isDisabled()) {
5053
+ this.dragOver.set(true);
5054
+ }
5055
+ }
5056
+ onDragOver(event) {
5057
+ event.preventDefault();
5058
+ }
5059
+ onDragLeave(event) {
5060
+ event.preventDefault();
5061
+ this.dragOver.set(false);
5062
+ }
5063
+ onDrop(event) {
5064
+ event.preventDefault();
5065
+ this.dragOver.set(false);
5066
+ if (this.isDisabled()) {
5067
+ return;
5068
+ }
5069
+ this.addFiles(event.dataTransfer?.files ?? null);
5070
+ }
5071
+ removeFile(file) {
5072
+ if (this.isDisabled()) {
5073
+ return;
5074
+ }
5075
+ const next = this.files().filter((f) => f !== file);
5076
+ this.files.set(next);
5077
+ this.onChange(next);
5078
+ this.onTouched();
5079
+ }
5080
+ addFiles(fileList) {
5081
+ if (!fileList || fileList.length === 0) {
5082
+ return;
5083
+ }
5084
+ const incoming = Array.from(fileList);
5085
+ const maxSizeMb = this.maxSizeMb();
5086
+ const accepted = [];
5087
+ const rejected = [];
5088
+ for (const file of incoming) {
5089
+ if (maxSizeMb !== null && file.size > maxSizeMb * 1024 * 1024) {
5090
+ rejected.push(this.oversizeMessage()(file.name, maxSizeMb));
5091
+ }
5092
+ else {
5093
+ accepted.push(file);
5094
+ }
5095
+ }
5096
+ this.rejections.set(rejected);
5097
+ if (accepted.length === 0) {
5098
+ return;
5099
+ }
5100
+ const next = this.multiple() ? [...this.files(), ...accepted] : accepted.slice(0, 1);
5101
+ this.files.set(next);
5102
+ this.onChange(next);
3181
5103
  this.onTouched();
3182
- this.committed.emit(this.value());
3183
5104
  }
3184
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Textarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
3185
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Textarea, isStandalone: true, selector: "gbt-textarea", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { committed: "committed" }, providers: [
5105
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: FileUpload, deps: [], target: i0.ɵɵFactoryTarget.Component });
5106
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: FileUpload, isStandalone: true, selector: "gbt-file-upload", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, dropLabel: { classPropertyName: "dropLabel", publicName: "dropLabel", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, oversizeMessage: { classPropertyName: "oversizeMessage", publicName: "oversizeMessage", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3186
5107
  {
3187
5108
  provide: NG_VALUE_ACCESSOR,
3188
- useExisting: forwardRef(() => Textarea),
5109
+ useExisting: forwardRef(() => FileUpload),
3189
5110
  multi: true,
3190
5111
  },
3191
- ], ngImport: i0, 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"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5112
+ ], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-file-upload\">\n @if (label()) {\n <span class=\"gbt-file-upload__label\" [id]=\"id() + '-label'\">{{ label() }}</span>\n }\n <button\n type=\"button\"\n class=\"gbt-file-upload__dropzone\"\n [class.gbt-file-upload__dropzone--drag-over]=\"dragOver()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"openPicker()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\"\n >\n <gbt-icon name=\"upload\" class=\"gbt-file-upload__icon\" aria-hidden=\"true\" />\n <span class=\"gbt-file-upload__hint\">{{ dropLabel() }}</span>\n </button>\n <input\n #fileInput\n type=\"file\"\n class=\"gbt-file-upload__input\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [multiple]=\"multiple()\"\n [attr.accept]=\"accept() || null\"\n [disabled]=\"isDisabled()\"\n (change)=\"onFilesSelected($event)\"\n />\n @if (rejections().length > 0) {\n <div class=\"gbt-file-upload__rejections\" role=\"alert\">\n <ul>\n @for (message of rejections(); track message) {\n <li>{{ message }}</li>\n }\n </ul>\n </div>\n }\n @if (files().length > 0) {\n <ul class=\"gbt-file-upload__files\">\n @for (file of files(); track file) {\n <li class=\"gbt-file-upload__file\">\n <span class=\"gbt-file-upload__file-name\">{{ file.name }}</span>\n <span class=\"gbt-file-upload__file-size\">{{ formatFileSize(file.size) }}</span>\n <button\n type=\"button\"\n class=\"gbt-file-upload__file-remove\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"removeLabel()(file.name)\"\n (click)=\"removeFile(file)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-file-upload__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-file-upload{display:flex;flex-direction:column;gap:.5rem}.gbt-file-upload__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-file-upload__dropzone{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:.5rem;width:100%;padding:1.5rem 1rem;background:var(--bg-panel);border:1px dashed var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),background .15s cubic-bezier(.4,0,.2,1)}.gbt-file-upload__dropzone:hover:not(:disabled){border-color:var(--primary)}.gbt-file-upload__dropzone:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-file-upload__dropzone--drag-over{background:color-mix(in srgb,var(--primary) 8%,var(--bg-panel));border-color:var(--primary)}.gbt-file-upload__dropzone:disabled{cursor:not-allowed;opacity:.5}.gbt-file-upload__icon{color:var(--text-discret)}.gbt-file-upload__hint{font-size:13px;text-align:center}.gbt-file-upload__input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.gbt-file-upload__rejections{font-size:.75rem;color:var(--color-error-text)}.gbt-file-upload__rejections ul{margin:0;padding:0;list-style:none}.gbt-file-upload__files{display:flex;flex-direction:column;gap:.375rem;margin:0;padding:0;list-style:none}.gbt-file-upload__file{box-sizing:border-box;display:flex;align-items:center;gap:.5rem;padding:.5rem .625rem;background:var(--bg-panel);border-radius:var(--site-border-radius-sm)}.gbt-file-upload__file-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;color:var(--text-primary)}.gbt-file-upload__file-size{flex-shrink:0;font-size:12px;color:var(--text-secondary)}.gbt-file-upload__file-remove{position:relative;display:inline-flex;flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer}.gbt-file-upload__file-remove:hover:not(:disabled){color:var(--text-primary)}.gbt-file-upload__file-remove:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-file-upload__file-remove:disabled{cursor:not-allowed;opacity:.5}.gbt-file-upload__file-remove:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-file-upload__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-file-upload__dropzone{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3192
5113
  }
3193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Textarea, decorators: [{
5114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: FileUpload, decorators: [{
3194
5115
  type: Component,
3195
- args: [{ selector: 'gbt-textarea', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
5116
+ args: [{ selector: 'gbt-file-upload', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3196
5117
  {
3197
5118
  provide: NG_VALUE_ACCESSOR,
3198
- useExisting: forwardRef(() => Textarea),
5119
+ useExisting: forwardRef(() => FileUpload),
3199
5120
  multi: true,
3200
5121
  },
3201
- ], 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"] }]
3202
- }], 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"] }] } });
5122
+ ], template: "<div class=\"gbt-file-upload\">\n @if (label()) {\n <span class=\"gbt-file-upload__label\" [id]=\"id() + '-label'\">{{ label() }}</span>\n }\n <button\n type=\"button\"\n class=\"gbt-file-upload__dropzone\"\n [class.gbt-file-upload__dropzone--drag-over]=\"dragOver()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (click)=\"openPicker()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\"\n >\n <gbt-icon name=\"upload\" class=\"gbt-file-upload__icon\" aria-hidden=\"true\" />\n <span class=\"gbt-file-upload__hint\">{{ dropLabel() }}</span>\n </button>\n <input\n #fileInput\n type=\"file\"\n class=\"gbt-file-upload__input\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [multiple]=\"multiple()\"\n [attr.accept]=\"accept() || null\"\n [disabled]=\"isDisabled()\"\n (change)=\"onFilesSelected($event)\"\n />\n @if (rejections().length > 0) {\n <div class=\"gbt-file-upload__rejections\" role=\"alert\">\n <ul>\n @for (message of rejections(); track message) {\n <li>{{ message }}</li>\n }\n </ul>\n </div>\n }\n @if (files().length > 0) {\n <ul class=\"gbt-file-upload__files\">\n @for (file of files(); track file) {\n <li class=\"gbt-file-upload__file\">\n <span class=\"gbt-file-upload__file-name\">{{ file.name }}</span>\n <span class=\"gbt-file-upload__file-size\">{{ formatFileSize(file.size) }}</span>\n <button\n type=\"button\"\n class=\"gbt-file-upload__file-remove\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"removeLabel()(file.name)\"\n (click)=\"removeFile(file)\"\n >\n <gbt-icon name=\"x\" aria-hidden=\"true\" />\n </button>\n </li>\n }\n </ul>\n }\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-file-upload__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-file-upload{display:flex;flex-direction:column;gap:.5rem}.gbt-file-upload__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-file-upload__dropzone{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:.5rem;width:100%;padding:1.5rem 1rem;background:var(--bg-panel);border:1px dashed var(--border-color);border-radius:var(--site-border-radius-sm);color:var(--text-secondary);cursor:pointer;transition:border-color .15s cubic-bezier(.4,0,.2,1),background .15s cubic-bezier(.4,0,.2,1)}.gbt-file-upload__dropzone:hover:not(:disabled){border-color:var(--primary)}.gbt-file-upload__dropzone:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-file-upload__dropzone--drag-over{background:color-mix(in srgb,var(--primary) 8%,var(--bg-panel));border-color:var(--primary)}.gbt-file-upload__dropzone:disabled{cursor:not-allowed;opacity:.5}.gbt-file-upload__icon{color:var(--text-discret)}.gbt-file-upload__hint{font-size:13px;text-align:center}.gbt-file-upload__input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.gbt-file-upload__rejections{font-size:.75rem;color:var(--color-error-text)}.gbt-file-upload__rejections ul{margin:0;padding:0;list-style:none}.gbt-file-upload__files{display:flex;flex-direction:column;gap:.375rem;margin:0;padding:0;list-style:none}.gbt-file-upload__file{box-sizing:border-box;display:flex;align-items:center;gap:.5rem;padding:.5rem .625rem;background:var(--bg-panel);border-radius:var(--site-border-radius-sm)}.gbt-file-upload__file-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;color:var(--text-primary)}.gbt-file-upload__file-size{flex-shrink:0;font-size:12px;color:var(--text-secondary)}.gbt-file-upload__file-remove{position:relative;display:inline-flex;flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer}.gbt-file-upload__file-remove:hover:not(:disabled){color:var(--text-primary)}.gbt-file-upload__file-remove:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-file-upload__file-remove:disabled{cursor:not-allowed;opacity:.5}.gbt-file-upload__file-remove:before{content:\"\";position:absolute;inset:50% auto auto 50%;width:max(100%,24px);height:max(100%,24px);transform:translate(-50%,-50%)}.gbt-file-upload__error{margin:0;font-size:.75rem;color:var(--color-error-text)}@media(prefers-reduced-motion:reduce){.gbt-file-upload__dropzone{transition:none}}\n"] }]
5123
+ }], propDecorators: { fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSizeMb: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeMb", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], dropLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropLabel", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], oversizeMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "oversizeMessage", required: false }] }] } });
3203
5124
 
3204
- let nextAutocompleteId = 0;
3205
- class Autocomplete {
3206
- elementRef = inject(ElementRef);
3207
- id = input(`gbt-autocomplete-${++nextAutocompleteId}`, /* @ts-ignore */
5125
+ class NotificationDot {
5126
+ count = input(null, /* @ts-ignore */
5127
+ ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
5128
+ max = input(99, /* @ts-ignore */
5129
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
5130
+ variant = input('error', /* @ts-ignore */
5131
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5132
+ hidden = input(false, /* @ts-ignore */
5133
+ ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
5134
+ showDot = computed(() => !this.hidden() && this.count() !== 0, /* @ts-ignore */
5135
+ ...(ngDevMode ? [{ debugName: "showDot" }] : /* istanbul ignore next */ []));
5136
+ displayValue = computed(() => {
5137
+ const count = this.count();
5138
+ if (count === null) {
5139
+ return '';
5140
+ }
5141
+ const max = this.max();
5142
+ return count > max ? `${max}+` : `${count}`;
5143
+ }, /* @ts-ignore */
5144
+ ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
5145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NotificationDot, deps: [], target: i0.ɵɵFactoryTarget.Component });
5146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: NotificationDot, isStandalone: true, selector: "gbt-notification-dot", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["gbtNotificationDot"], ngImport: i0, template: "<span class=\"gbt-notification-dot__anchor\">\n <ng-content></ng-content>\n</span>\n@if (showDot()) {\n <span\n class=\"gbt-notification-dot__badge\"\n [class.gbt-notification-dot__badge--count]=\"count() !== null\"\n [attr.data-variant]=\"variant()\"\n aria-hidden=\"true\"\n >{{ displayValue() }}</span>\n}\n", styles: [":host{position:relative;display:inline-flex}.gbt-notification-dot__anchor{display:inline-flex}.gbt-notification-dot__badge{box-sizing:border-box;position:absolute;top:-4px;right:-4px;display:flex;align-items:center;justify-content:center;min-width:8px;height:8px;padding:0;background:var(--color-error-base);border:2px solid var(--bg-principal);border-radius:999px}.gbt-notification-dot__badge[data-variant=warning]{background:var(--color-warning-base)}.gbt-notification-dot__badge[data-variant=success]{background:var(--color-success-base)}.gbt-notification-dot__badge[data-variant=info]{background:var(--color-info-vivid-base)}.gbt-notification-dot__badge--count{min-width:16px;height:16px;padding:0 4px;background:var(--color-error-bg);color:var(--color-error-bg-text);font-size:10px;font-weight:700;line-height:1}.gbt-notification-dot__badge--count[data-variant=warning]{background:var(--color-warning-bg);color:var(--color-warning-bg-text)}.gbt-notification-dot__badge--count[data-variant=success]{background:var(--color-success-bg);color:var(--color-success-bg-text)}.gbt-notification-dot__badge--count[data-variant=info]{background:var(--color-info-bg);color:var(--color-info-bg-text)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5147
+ }
5148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NotificationDot, decorators: [{
5149
+ type: Component,
5150
+ args: [{ selector: 'gbt-notification-dot', standalone: true, exportAs: 'gbtNotificationDot', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"gbt-notification-dot__anchor\">\n <ng-content></ng-content>\n</span>\n@if (showDot()) {\n <span\n class=\"gbt-notification-dot__badge\"\n [class.gbt-notification-dot__badge--count]=\"count() !== null\"\n [attr.data-variant]=\"variant()\"\n aria-hidden=\"true\"\n >{{ displayValue() }}</span>\n}\n", styles: [":host{position:relative;display:inline-flex}.gbt-notification-dot__anchor{display:inline-flex}.gbt-notification-dot__badge{box-sizing:border-box;position:absolute;top:-4px;right:-4px;display:flex;align-items:center;justify-content:center;min-width:8px;height:8px;padding:0;background:var(--color-error-base);border:2px solid var(--bg-principal);border-radius:999px}.gbt-notification-dot__badge[data-variant=warning]{background:var(--color-warning-base)}.gbt-notification-dot__badge[data-variant=success]{background:var(--color-success-base)}.gbt-notification-dot__badge[data-variant=info]{background:var(--color-info-vivid-base)}.gbt-notification-dot__badge--count{min-width:16px;height:16px;padding:0 4px;background:var(--color-error-bg);color:var(--color-error-bg-text);font-size:10px;font-weight:700;line-height:1}.gbt-notification-dot__badge--count[data-variant=warning]{background:var(--color-warning-bg);color:var(--color-warning-bg-text)}.gbt-notification-dot__badge--count[data-variant=success]{background:var(--color-success-bg);color:var(--color-success-bg-text)}.gbt-notification-dot__badge--count[data-variant=info]{background:var(--color-info-bg);color:var(--color-info-bg-text)}\n"] }]
5151
+ }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }] } });
5152
+
5153
+ let nextId = 0;
5154
+ class TagInput {
5155
+ inputRef = viewChild('input', /* @ts-ignore */
5156
+ ...(ngDevMode ? [{ debugName: "inputRef" }] : /* istanbul ignore next */ []));
5157
+ id = input(`gbt-tag-input-${++nextId}`, /* @ts-ignore */
3208
5158
  ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3209
5159
  label = input('', /* @ts-ignore */
3210
5160
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3211
5161
  placeholder = input('', /* @ts-ignore */
3212
5162
  ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3213
5163
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3214
- required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3215
5164
  errorMessage = input(null, /* @ts-ignore */
3216
5165
  ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
3217
- search = input.required(/* @ts-ignore */
3218
- ...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
3219
- displayFn = input((item) => String(item), /* @ts-ignore */
3220
- ...(ngDevMode ? [{ debugName: "displayFn" }] : /* istanbul ignore next */ []));
3221
- itemTemplate = input(/* @ts-ignore */
3222
- ...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
3223
- debounceMs = input(300, /* @ts-ignore */
3224
- ...(ngDevMode ? [{ debugName: "debounceMs" }] : /* istanbul ignore next */ []));
3225
- minLength = input(1, /* @ts-ignore */
3226
- ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
3227
- loadingMessage = input('Searching…', /* @ts-ignore */
3228
- ...(ngDevMode ? [{ debugName: "loadingMessage" }] : /* istanbul ignore next */ []));
3229
- noResultsMessage = input('No results', /* @ts-ignore */
3230
- ...(ngDevMode ? [{ debugName: "noResultsMessage" }] : /* istanbul ignore next */ []));
3231
- searchErrorMessage = input('Search failed', /* @ts-ignore */
3232
- ...(ngDevMode ? [{ debugName: "searchErrorMessage" }] : /* istanbul ignore next */ []));
3233
- resultsAnnouncement = input((count) => `${count} result${count !== 1 ? 's' : ''}`, /* @ts-ignore */
3234
- ...(ngDevMode ? [{ debugName: "resultsAnnouncement" }] : /* istanbul ignore next */ []));
3235
- itemSelected = output();
3236
- query = signal('', /* @ts-ignore */
3237
- ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
3238
- open = signal(false, /* @ts-ignore */
3239
- ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
3240
- results = signal([], /* @ts-ignore */
3241
- ...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
3242
- loading = signal(false, /* @ts-ignore */
3243
- ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
3244
- searchFailed = signal(false, /* @ts-ignore */
3245
- ...(ngDevMode ? [{ debugName: "searchFailed" }] : /* istanbul ignore next */ []));
3246
- activeIndex = signal(0, /* @ts-ignore */
3247
- ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
3248
- selectedItem = signal(null, /* @ts-ignore */
3249
- ...(ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []));
3250
- panelStyle = signal(null, /* @ts-ignore */
3251
- ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
5166
+ separatorKeys = input(['Enter', ','], /* @ts-ignore */
5167
+ ...(ngDevMode ? [{ debugName: "separatorKeys" }] : /* istanbul ignore next */ []));
5168
+ allowDuplicates = input(false, { ...(ngDevMode ? { debugName: "allowDuplicates" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5169
+ color = input('#6b7280', /* @ts-ignore */
5170
+ ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
5171
+ removeLabel = input((value) => `Remove ${value}`, /* @ts-ignore */
5172
+ ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
5173
+ tags = signal([], /* @ts-ignore */
5174
+ ...(ngDevMode ? [{ debugName: "tags" }] : /* istanbul ignore next */ []));
5175
+ draft = signal('', /* @ts-ignore */
5176
+ ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
3252
5177
  formDisabled = signal(false, /* @ts-ignore */
3253
5178
  ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
3254
5179
  isDisabled = computed(() => this.disabled() || this.formDisabled(), /* @ts-ignore */
3255
5180
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
3256
- hasNoResults = computed(() => this.open() && !this.loading() && !this.searchFailed() && this.results().length === 0, /* @ts-ignore */
3257
- ...(ngDevMode ? [{ debugName: "hasNoResults" }] : /* istanbul ignore next */ []));
3258
- activeOptionId = computed(() => this.open() && this.results().length > 0 ? `${this.id()}-option-${this.activeIndex()}` : null, /* @ts-ignore */
3259
- ...(ngDevMode ? [{ debugName: "activeOptionId" }] : /* istanbul ignore next */ []));
3260
5181
  onChange = () => { };
3261
5182
  onTouched = () => { };
3262
- requestSeq = 0;
3263
- debounceHandle;
3264
- subscription;
3265
- setDisabledState(isDisabled) {
3266
- this.formDisabled.set(isDisabled);
3267
- }
3268
5183
  writeValue(value) {
3269
- this.selectedItem.set(value);
3270
- this.query.set(value === null || value === undefined ? '' : this.displayFn()(value));
5184
+ this.tags.set(value ?? []);
3271
5185
  }
3272
5186
  registerOnChange(fn) {
3273
5187
  this.onChange = fn;
@@ -3275,164 +5189,221 @@ class Autocomplete {
3275
5189
  registerOnTouched(fn) {
3276
5190
  this.onTouched = fn;
3277
5191
  }
3278
- onInput(event) {
3279
- const value = event.target.value;
3280
- this.query.set(value);
3281
- this.activeIndex.set(0);
3282
- if (this.selectedItem() !== null) {
3283
- this.selectedItem.set(null);
3284
- this.onChange(null);
5192
+ setDisabledState(isDisabled) {
5193
+ this.formDisabled.set(isDisabled);
5194
+ }
5195
+ focusInput() {
5196
+ if (!this.isDisabled()) {
5197
+ this.inputRef()?.nativeElement.focus();
3285
5198
  }
3286
- this.scheduleSearch(value);
3287
5199
  }
3288
- onFocus() {
3289
- if (this.query().trim().length >= this.minLength() &&
3290
- (this.results().length > 0 || this.searchFailed())) {
3291
- this.open.set(true);
3292
- this.updatePanelPosition();
5200
+ onInputChange(event) {
5201
+ this.draft.set(event.target.value);
5202
+ }
5203
+ onInputKeydown(event) {
5204
+ if (this.separatorKeys().includes(event.key)) {
5205
+ event.preventDefault();
5206
+ this.commitDraft();
5207
+ return;
5208
+ }
5209
+ if (event.key === 'Backspace' && this.draft() === '' && this.tags().length > 0) {
5210
+ event.preventDefault();
5211
+ this.removeTagAt(this.tags().length - 1);
3293
5212
  }
3294
5213
  }
3295
5214
  onBlur() {
5215
+ this.commitDraft();
3296
5216
  this.onTouched();
3297
- setTimeout(() => {
3298
- if (!this.elementRef.nativeElement.contains(document.activeElement)) {
3299
- this.open.set(false);
3300
- }
3301
- }, 200);
3302
5217
  }
3303
- scheduleSearch(value) {
3304
- clearTimeout(this.debounceHandle);
3305
- if (value.trim().length < this.minLength()) {
3306
- this.requestSeq++;
3307
- this.subscription?.unsubscribe();
3308
- this.open.set(false);
3309
- this.results.set([]);
3310
- this.loading.set(false);
3311
- this.searchFailed.set(false);
5218
+ removeTagAt(index) {
5219
+ if (this.isDisabled()) {
3312
5220
  return;
3313
5221
  }
3314
- this.debounceHandle = setTimeout(() => this.runSearch(value), this.debounceMs());
3315
- }
3316
- runSearch(query) {
3317
- const seq = ++this.requestSeq;
3318
- this.subscription?.unsubscribe();
3319
- this.loading.set(true);
3320
- this.searchFailed.set(false);
3321
- this.open.set(true);
3322
- this.updatePanelPosition();
3323
- const applyResults = (items) => {
3324
- if (seq !== this.requestSeq)
3325
- return;
3326
- this.results.set(items);
3327
- this.loading.set(false);
3328
- this.activeIndex.set(0);
3329
- this.updatePanelPosition();
3330
- };
3331
- const applyError = () => {
3332
- if (seq !== this.requestSeq)
3333
- return;
3334
- this.results.set([]);
3335
- this.loading.set(false);
3336
- this.searchFailed.set(true);
3337
- this.updatePanelPosition();
3338
- };
3339
- const result = this.search()(query);
3340
- if (isObservable(result)) {
3341
- this.subscription = result.subscribe({ next: applyResults, error: applyError });
3342
- }
3343
- else {
3344
- result.then(applyResults, applyError);
3345
- }
3346
- }
3347
- updatePanelPosition() {
3348
- if (!this.open()) {
5222
+ const next = this.tags().filter((_, i) => i !== index);
5223
+ this.tags.set(next);
5224
+ this.onChange(next);
5225
+ }
5226
+ commitDraft() {
5227
+ const value = this.draft().trim();
5228
+ this.draft.set('');
5229
+ if (!value || this.isDisabled()) {
3349
5230
  return;
3350
5231
  }
3351
- const trigger = this.elementRef.nativeElement.querySelector('.gbt-autocomplete__input');
3352
- if (!trigger) {
5232
+ if (!this.allowDuplicates() && this.tags().includes(value)) {
3353
5233
  return;
3354
5234
  }
3355
- const rect = trigger.getBoundingClientRect();
3356
- this.panelStyle.set({
3357
- top: `${rect.bottom + 6}px`,
3358
- left: `${rect.left}px`,
3359
- width: `${rect.width}px`,
3360
- });
5235
+ const next = [...this.tags(), value];
5236
+ this.tags.set(next);
5237
+ this.onChange(next);
3361
5238
  }
3362
- selectOption(item) {
3363
- this.selectedItem.set(item);
3364
- this.query.set(this.displayFn()(item));
3365
- this.results.set([]);
3366
- this.open.set(false);
3367
- this.onChange(item);
3368
- this.onTouched();
3369
- this.itemSelected.emit(item);
5239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TagInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
5240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: TagInput, isStandalone: true, selector: "gbt-tag-input", 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 }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, separatorKeys: { classPropertyName: "separatorKeys", publicName: "separatorKeys", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
5241
+ {
5242
+ provide: NG_VALUE_ACCESSOR,
5243
+ useExisting: forwardRef(() => TagInput),
5244
+ multi: true,
5245
+ },
5246
+ ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-tag-input\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-tag-input__label\">{{ label() }}</label>\n }\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"gbt-tag-input__field\"\n [class.gbt-tag-input__field--disabled]=\"isDisabled()\"\n (click)=\"focusInput()\"\n >\n @for (tag of tags(); track tag; let i = $index) {\n <gbt-tag\n [color]=\"color()\"\n [removable]=\"!isDisabled()\"\n [disabled]=\"isDisabled()\"\n [removeLabel]=\"removeLabel()(tag)\"\n (removed)=\"removeTagAt(i)\"\n >\n {{ tag }}\n </gbt-tag>\n }\n <input\n #input\n type=\"text\"\n [id]=\"id()\"\n class=\"gbt-tag-input__input\"\n [placeholder]=\"tags().length === 0 ? placeholder() : ''\"\n [disabled]=\"isDisabled()\"\n [value]=\"draft()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInputChange($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-tag-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-tag-input{display:flex;flex-direction:column;gap:.375rem}.gbt-tag-input__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-tag-input__field{box-sizing:border-box;display:flex;flex-wrap:wrap;align-items:center;gap:.375rem;min-height:40px;padding:6px 8px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);cursor:text}.gbt-tag-input__field:focus-within{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-tag-input__field--disabled{cursor:not-allowed;opacity:.5}.gbt-tag-input__input{flex:1;min-width:80px;padding:2px 0;background:none;border:none;color:var(--text-primary);font-size:14px}.gbt-tag-input__input:focus{outline:none}.gbt-tag-input__input:disabled{cursor:not-allowed}.gbt-tag-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"], dependencies: [{ kind: "component", type: Tag, selector: "gbt-tag", inputs: ["color", "removable", "removeLabel", "disabled"], outputs: ["removed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5247
+ }
5248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: TagInput, decorators: [{
5249
+ type: Component,
5250
+ args: [{ selector: 'gbt-tag-input', standalone: true, imports: [Tag], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
5251
+ {
5252
+ provide: NG_VALUE_ACCESSOR,
5253
+ useExisting: forwardRef(() => TagInput),
5254
+ multi: true,
5255
+ },
5256
+ ], template: "<div class=\"gbt-tag-input\">\n @if (label()) {\n <label [for]=\"id()\" class=\"gbt-tag-input__label\">{{ label() }}</label>\n }\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"gbt-tag-input__field\"\n [class.gbt-tag-input__field--disabled]=\"isDisabled()\"\n (click)=\"focusInput()\"\n >\n @for (tag of tags(); track tag; let i = $index) {\n <gbt-tag\n [color]=\"color()\"\n [removable]=\"!isDisabled()\"\n [disabled]=\"isDisabled()\"\n [removeLabel]=\"removeLabel()(tag)\"\n (removed)=\"removeTagAt(i)\"\n >\n {{ tag }}\n </gbt-tag>\n }\n <input\n #input\n type=\"text\"\n [id]=\"id()\"\n class=\"gbt-tag-input__input\"\n [placeholder]=\"tags().length === 0 ? placeholder() : ''\"\n [disabled]=\"isDisabled()\"\n [value]=\"draft()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? id() + '-error' : null\"\n (input)=\"onInputChange($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n </div>\n @if (errorMessage()) {\n <p [id]=\"id() + '-error'\" class=\"gbt-tag-input__error\" role=\"alert\">{{ errorMessage() }}</p>\n }\n</div>\n", styles: [".gbt-tag-input{display:flex;flex-direction:column;gap:.375rem}.gbt-tag-input__label{font-size:.8125rem;font-weight:600;color:var(--text-secondary)}.gbt-tag-input__field{box-sizing:border-box;display:flex;flex-wrap:wrap;align-items:center;gap:.375rem;min-height:40px;padding:6px 8px;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:var(--site-border-radius-sm);cursor:text}.gbt-tag-input__field:focus-within{border-color:var(--primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--primary) 12%,transparent)}.gbt-tag-input__field--disabled{cursor:not-allowed;opacity:.5}.gbt-tag-input__input{flex:1;min-width:80px;padding:2px 0;background:none;border:none;color:var(--text-primary);font-size:14px}.gbt-tag-input__input:focus{outline:none}.gbt-tag-input__input:disabled{cursor:not-allowed}.gbt-tag-input__error{margin:0;font-size:.75rem;color:var(--color-error-text)}\n"] }]
5257
+ }], propDecorators: { inputRef: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], 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 }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], separatorKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorKeys", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }] } });
5258
+
5259
+ function flattenTree(nodes, expandedIds, depth = 0, parentId = null) {
5260
+ const result = [];
5261
+ for (const node of nodes) {
5262
+ const hasChildren = !!node.children && node.children.length > 0;
5263
+ result.push({ node, depth, hasChildren, parentId });
5264
+ if (hasChildren && expandedIds.has(node.id)) {
5265
+ result.push(...flattenTree(node.children, expandedIds, depth + 1, node.id));
5266
+ }
3370
5267
  }
3371
- onKeydown(event) {
3372
- if (this.isDisabled()) {
3373
- return;
5268
+ return result;
5269
+ }
5270
+
5271
+ class Tree {
5272
+ elementRef = inject(ElementRef);
5273
+ injector = inject(Injector);
5274
+ items = input.required(/* @ts-ignore */
5275
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
5276
+ ariaLabel = input('', /* @ts-ignore */
5277
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
5278
+ selectedId = model(null, /* @ts-ignore */
5279
+ ...(ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []));
5280
+ expandedIds = model([], /* @ts-ignore */
5281
+ ...(ngDevMode ? [{ debugName: "expandedIds" }] : /* istanbul ignore next */ []));
5282
+ expandLabel = input('Expand', /* @ts-ignore */
5283
+ ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
5284
+ collapseLabel = input('Collapse', /* @ts-ignore */
5285
+ ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
5286
+ focusedId = signal(null, /* @ts-ignore */
5287
+ ...(ngDevMode ? [{ debugName: "focusedId" }] : /* istanbul ignore next */ []));
5288
+ expandedSet = computed(() => new Set(this.expandedIds()), /* @ts-ignore */
5289
+ ...(ngDevMode ? [{ debugName: "expandedSet" }] : /* istanbul ignore next */ []));
5290
+ flatNodes = computed(() => flattenTree(this.items(), this.expandedSet()), /* @ts-ignore */
5291
+ ...(ngDevMode ? [{ debugName: "flatNodes" }] : /* istanbul ignore next */ []));
5292
+ activeId = computed(() => {
5293
+ const focused = this.focusedId();
5294
+ const flat = this.flatNodes();
5295
+ if (focused && flat.some((f) => f.node.id === focused)) {
5296
+ return focused;
3374
5297
  }
3375
- if (event.key === 'Escape') {
3376
- if (this.open()) {
3377
- event.preventDefault();
3378
- event.stopPropagation();
3379
- this.open.set(false);
3380
- }
3381
- return;
5298
+ const selected = this.selectedId();
5299
+ if (selected && flat.some((f) => f.node.id === selected)) {
5300
+ return selected;
3382
5301
  }
3383
- if (!this.open() || this.results().length === 0) {
5302
+ return flat[0]?.node.id ?? null;
5303
+ }, /* @ts-ignore */
5304
+ ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
5305
+ isExpanded(id) {
5306
+ return this.expandedSet().has(id);
5307
+ }
5308
+ toggle(id) {
5309
+ const set = new Set(this.expandedIds());
5310
+ if (set.has(id)) {
5311
+ set.delete(id);
5312
+ }
5313
+ else {
5314
+ set.add(id);
5315
+ }
5316
+ this.expandedIds.set([...set]);
5317
+ }
5318
+ select(node) {
5319
+ this.selectedId.set(node.id);
5320
+ this.focusedId.set(node.id);
5321
+ }
5322
+ onItemClick(flat) {
5323
+ this.select(flat.node);
5324
+ if (flat.hasChildren) {
5325
+ this.toggle(flat.node.id);
5326
+ }
5327
+ }
5328
+ onKeydown(event) {
5329
+ const flat = this.flatNodes();
5330
+ const index = flat.findIndex((f) => f.node.id === this.activeId());
5331
+ if (index === -1) {
3384
5332
  return;
3385
5333
  }
3386
- const results = this.results();
5334
+ const current = flat[index];
3387
5335
  switch (event.key) {
3388
5336
  case 'ArrowDown':
3389
5337
  event.preventDefault();
3390
- this.activeIndex.update((i) => Math.min(i + 1, results.length - 1));
5338
+ this.focusIndex(Math.min(index + 1, flat.length - 1));
3391
5339
  break;
3392
5340
  case 'ArrowUp':
3393
5341
  event.preventDefault();
3394
- this.activeIndex.update((i) => Math.max(i - 1, 0));
5342
+ this.focusIndex(Math.max(index - 1, 0));
3395
5343
  break;
3396
- case 'Enter': {
5344
+ case 'ArrowRight':
3397
5345
  event.preventDefault();
3398
- const active = results[this.activeIndex()];
3399
- if (active) {
3400
- this.selectOption(active);
5346
+ if (current.hasChildren && !this.isExpanded(current.node.id)) {
5347
+ this.toggle(current.node.id);
5348
+ }
5349
+ else if (current.hasChildren) {
5350
+ this.focusIndex(index + 1);
3401
5351
  }
3402
5352
  break;
3403
- }
5353
+ case 'ArrowLeft':
5354
+ event.preventDefault();
5355
+ if (current.hasChildren && this.isExpanded(current.node.id)) {
5356
+ this.toggle(current.node.id);
5357
+ }
5358
+ else if (current.parentId) {
5359
+ const parentIndex = flat.findIndex((f) => f.node.id === current.parentId);
5360
+ if (parentIndex !== -1) {
5361
+ this.focusIndex(parentIndex);
5362
+ }
5363
+ }
5364
+ break;
5365
+ case 'Home':
5366
+ event.preventDefault();
5367
+ this.focusIndex(0);
5368
+ break;
5369
+ case 'End':
5370
+ event.preventDefault();
5371
+ this.focusIndex(flat.length - 1);
5372
+ break;
5373
+ case 'Enter':
5374
+ case ' ':
5375
+ event.preventDefault();
5376
+ this.select(current.node);
5377
+ break;
5378
+ default:
5379
+ return;
3404
5380
  }
3405
5381
  }
3406
- ngOnDestroy() {
3407
- clearTimeout(this.debounceHandle);
3408
- this.subscription?.unsubscribe();
5382
+ focusIndex(index) {
5383
+ const target = this.flatNodes()[index];
5384
+ if (!target) {
5385
+ return;
5386
+ }
5387
+ this.focusedId.set(target.node.id);
5388
+ afterNextRender(() => {
5389
+ const host = this.elementRef.nativeElement;
5390
+ host.querySelector(`[data-node-id="${cssEscape(target.node.id)}"]`)?.focus();
5391
+ }, { injector: this.injector });
3409
5392
  }
3410
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Autocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
3411
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", 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: [
3412
- {
3413
- provide: NG_VALUE_ACCESSOR,
3414
- useExisting: forwardRef(() => Autocomplete),
3415
- multi: true,
3416
- },
3417
- ], 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 });
5393
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tree, deps: [], target: i0.ɵɵFactoryTarget.Component });
5394
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: Tree, isStandalone: true, selector: "gbt-tree", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, expandedIds: { classPropertyName: "expandedIds", publicName: "expandedIds", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedId: "selectedIdChange", expandedIds: "expandedIdsChange" }, ngImport: i0, template: "<ul\n class=\"gbt-tree\"\n role=\"tree\"\n tabindex=\"-1\"\n [attr.aria-label]=\"ariaLabel() || null\"\n (keydown)=\"onKeydown($event)\"\n>\n @for (flat of flatNodes(); track flat.node.id) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"gbt-tree__item\"\n role=\"treeitem\"\n [attr.data-node-id]=\"flat.node.id\"\n [attr.aria-level]=\"flat.depth + 1\"\n [attr.aria-expanded]=\"flat.hasChildren ? isExpanded(flat.node.id) : null\"\n [attr.aria-selected]=\"selectedId() === flat.node.id\"\n [style.paddingLeft.px]=\"flat.depth * 20\"\n [attr.tabindex]=\"activeId() === flat.node.id ? 0 : -1\"\n (click)=\"onItemClick(flat)\"\n >\n @if (flat.hasChildren) {\n <button\n type=\"button\"\n class=\"gbt-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isExpanded(flat.node.id) ? collapseLabel() : expandLabel()\"\n (click)=\"toggle(flat.node.id); $event.stopPropagation()\"\n >\n <gbt-icon\n name=\"chevron-right\"\n class=\"gbt-tree__chevron\"\n [class.gbt-tree__chevron--expanded]=\"isExpanded(flat.node.id)\"\n aria-hidden=\"true\"\n />\n </button>\n } @else {\n <span class=\"gbt-tree__spacer\"></span>\n }\n @if (flat.node.icon) {\n <gbt-icon [name]=\"flat.node.icon\" class=\"gbt-tree__icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-tree__label\">{{ flat.node.label }}</span>\n </li>\n }\n</ul>\n", styles: [".gbt-tree{margin:0;padding:0;list-style:none}.gbt-tree__item{box-sizing:border-box;display:flex;align-items:center;gap:.375rem;height:32px;padding-right:.5rem;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-tree__item:hover{background:var(--bg-hover)}.gbt-tree__item:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-tree__item[aria-selected=true]{background:var(--color-info-bg);color:var(--color-info-bg-text);font-weight:600}.gbt-tree__toggle{position:relative;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:20px;height:20px;background:none;border:none;color:var(--text-secondary);cursor:pointer}.gbt-tree__spacer{flex-shrink:0;width:20px}.gbt-tree__chevron{transition:transform .15s cubic-bezier(.4,0,.2,1)}.gbt-tree__chevron--expanded{transform:rotate(90deg)}.gbt-tree__icon{flex-shrink:0;color:var(--text-secondary)}.gbt-tree__label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media(prefers-reduced-motion:reduce){.gbt-tree__chevron{transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3418
5395
  }
3419
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Autocomplete, decorators: [{
5396
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Tree, decorators: [{
3420
5397
  type: Component,
3421
- args: [{ selector: 'gbt-autocomplete', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3422
- '(window:scroll)': 'updatePanelPosition()',
3423
- '(window:resize)': 'updatePanelPosition()',
3424
- }, providers: [
3425
- {
3426
- provide: NG_VALUE_ACCESSOR,
3427
- useExisting: forwardRef(() => Autocomplete),
3428
- multi: true,
3429
- },
3430
- ], 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"] }]
3431
- }], 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"] }] } });
5398
+ args: [{ selector: 'gbt-tree', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul\n class=\"gbt-tree\"\n role=\"tree\"\n tabindex=\"-1\"\n [attr.aria-label]=\"ariaLabel() || null\"\n (keydown)=\"onKeydown($event)\"\n>\n @for (flat of flatNodes(); track flat.node.id) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <li\n class=\"gbt-tree__item\"\n role=\"treeitem\"\n [attr.data-node-id]=\"flat.node.id\"\n [attr.aria-level]=\"flat.depth + 1\"\n [attr.aria-expanded]=\"flat.hasChildren ? isExpanded(flat.node.id) : null\"\n [attr.aria-selected]=\"selectedId() === flat.node.id\"\n [style.paddingLeft.px]=\"flat.depth * 20\"\n [attr.tabindex]=\"activeId() === flat.node.id ? 0 : -1\"\n (click)=\"onItemClick(flat)\"\n >\n @if (flat.hasChildren) {\n <button\n type=\"button\"\n class=\"gbt-tree__toggle\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isExpanded(flat.node.id) ? collapseLabel() : expandLabel()\"\n (click)=\"toggle(flat.node.id); $event.stopPropagation()\"\n >\n <gbt-icon\n name=\"chevron-right\"\n class=\"gbt-tree__chevron\"\n [class.gbt-tree__chevron--expanded]=\"isExpanded(flat.node.id)\"\n aria-hidden=\"true\"\n />\n </button>\n } @else {\n <span class=\"gbt-tree__spacer\"></span>\n }\n @if (flat.node.icon) {\n <gbt-icon [name]=\"flat.node.icon\" class=\"gbt-tree__icon\" aria-hidden=\"true\" />\n }\n <span class=\"gbt-tree__label\">{{ flat.node.label }}</span>\n </li>\n }\n</ul>\n", styles: [".gbt-tree{margin:0;padding:0;list-style:none}.gbt-tree__item{box-sizing:border-box;display:flex;align-items:center;gap:.375rem;height:32px;padding-right:.5rem;border-radius:var(--site-border-radius-sm);color:var(--text-primary);font-size:13px;cursor:pointer}.gbt-tree__item:hover{background:var(--bg-hover)}.gbt-tree__item:focus-visible{outline:2px solid var(--primary);outline-offset:-2px}.gbt-tree__item[aria-selected=true]{background:var(--color-info-bg);color:var(--color-info-bg-text);font-weight:600}.gbt-tree__toggle{position:relative;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:20px;height:20px;background:none;border:none;color:var(--text-secondary);cursor:pointer}.gbt-tree__spacer{flex-shrink:0;width:20px}.gbt-tree__chevron{transition:transform .15s cubic-bezier(.4,0,.2,1)}.gbt-tree__chevron--expanded{transform:rotate(90deg)}.gbt-tree__icon{flex-shrink:0;color:var(--text-secondary)}.gbt-tree__label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media(prefers-reduced-motion:reduce){.gbt-tree__chevron{transition:none}}\n"] }]
5399
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], expandedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedIds", required: false }] }, { type: i0.Output, args: ["expandedIdsChange"] }], expandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandLabel", required: false }] }], collapseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseLabel", required: false }] }] } });
5400
+ function cssEscape(value) {
5401
+ return typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(value) : value.replace(/"/g, '\\"');
5402
+ }
3432
5403
 
3433
5404
  /**
3434
5405
  * Generated bundle index. Do not edit.
3435
5406
  */
3436
5407
 
3437
- export { Alert, 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, Tag, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
5408
+ export { Accordion, AccordionItem, Alert, AppShell, Autocomplete, Avatar, AvatarGroup, Badge, BarChart, BarSeries, Breadcrumb, Button, CHART_CONTEXT, Card, ChartAxis, ChartEmpty, ChartFrame, ChartLegend, ChartTable, ChartTooltip, Checkbox, ConfirmDangerModal, DatePicker, DateRangePicker, DescriptionList, DimensionCard, Divider, Drawer, EmptyState, FileUpload, FunnelChart, GABARIT_VERSION, GaugeBar, GbtInput, Icon, IconRegistry, LineChart, LineSeries, ListToolbar, Menu, Modal, NotificationDot, Pagination, PieChart, Popover, RadioGroup, SearchBar, SegmentedControl, Select, Skeleton, Slider, Sparkline, Spinner, Stepper, Switch, Tab, Table, Tabs, Tag, TagInput, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, Tree, arcPath, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
3438
5409
  //# sourceMappingURL=masmarino-gabarit.mjs.map