@guildofgleks/ui 0.0.1 → 0.2.2

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,12 +1,17 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { TemplateRef, Type, Injector, InjectionToken, OnDestroy, Signal } from '@angular/core';
2
+ import { TemplateRef, Type, Injector, InjectionToken, OnDestroy, DoCheck, Signal, ModelSignal, ElementRef } from '@angular/core';
3
3
  import { ControlValueAccessor } from '@angular/forms';
4
+ import * as _angular_platform_browser from '@angular/platform-browser';
4
5
  import * as _guildofgleks_ui from '@guildofgleks/ui';
5
6
 
6
- type GogSize = 'sm' | 'md' | 'lg';
7
+ type GogSize = 'xsm' | 'sm' | 'md' | 'lg' | 'slg';
7
8
  type GogVariant = 'primary' | 'secondary' | 'outline' | 'ghost';
9
+ type GogSpinnerVariant = 'runic' | 'ring' | 'custom';
8
10
  type GogTagVariant = 'success' | 'danger' | 'warning' | 'info';
9
11
  type GogTagShape = 'rounded' | 'pill';
12
+ type GogSkeletonShape = 'text' | 'circle' | 'rect';
13
+ type GogSkeletonAnimation = 'pulse' | 'wave' | 'none';
14
+ type GogPaginatorRangeMode = 'window' | 'ellipsis';
10
15
 
11
16
  declare class ButtonComponent {
12
17
  variant: _angular_core.InputSignal<GogVariant>;
@@ -14,22 +19,42 @@ declare class ButtonComponent {
14
19
  disabled: _angular_core.InputSignal<boolean>;
15
20
  fullWidth: _angular_core.InputSignal<boolean>;
16
21
  type: _angular_core.InputSignal<"button" | "submit" | "reset">;
17
- debounce: _angular_core.InputSignal<number>;
18
22
  loading: _angular_core.InputSignal<boolean>;
23
+ /**
24
+ * Minimum time, in ms, between accepted clicks. This is a spam/double-click
25
+ * guard, not a delay before the first click fires: the first click in a
26
+ * window is emitted immediately (leading edge), and any further clicks
27
+ * within `debounce` ms are silently dropped until the window elapses.
28
+ */
29
+ debounce: _angular_core.InputSignal<number>;
30
+ /**
31
+ * Accessible name for the button, forwarded to the native <button>.
32
+ * Setting `aria-label` directly on <gog-button> in a template does NOT
33
+ * work — that attribute lands on the custom element host, not on the
34
+ * actual interactive <button> inside it, so assistive tech never sees it.
35
+ * Use this input instead, especially for icon-only buttons.
36
+ */
37
+ ariaLabel: _angular_core.InputSignal<string | null>;
19
38
  gogClick: _angular_core.OutputEmitterRef<MouseEvent>;
39
+ /** Fully non-interactive: excluded from tab order via the native `disabled` attribute. */
40
+ protected isNativeDisabled: _angular_core.Signal<boolean>;
41
+ /** Logically blocked from activating (disabled OR loading), used to guard click handling. */
20
42
  protected isDisabled: _angular_core.Signal<boolean>;
43
+ private static readonly SPINNER_SIZE_BY_BUTTON_SIZE;
21
44
  protected spinnerSize: _angular_core.Signal<GogSize>;
22
45
  private readonly destroyRef;
23
46
  private readonly click$;
24
47
  constructor();
25
48
  protected onClick(event: MouseEvent): void;
26
49
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ButtonComponent, never>;
27
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "gog-button", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "debounce": { "alias": "debounce"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, { "gogClick": "gogClick"; }, never, ["*"], true, never>;
50
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "gog-button", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "debounce": { "alias": "debounce"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "gogClick": "gogClick"; }, never, ["*"], true, never>;
28
51
  }
29
52
 
30
53
  interface GogAccordionItem {
31
54
  id: string | number;
32
55
  title: string;
56
+ /** When true, the item's header is non-interactive and skipped by keyboard navigation. */
57
+ disabled?: boolean;
33
58
  [key: string]: unknown;
34
59
  }
35
60
  interface GogAccordionHeaderContext {
@@ -62,24 +87,52 @@ declare class GogAccordionChevronDirective {
62
87
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<GogAccordionChevronDirective, "[gogAccordionChevron]", never, {}, {}, never, never, true, never>;
63
88
  }
64
89
  declare class AccordionComponent {
65
- private readonly host;
90
+ private static nextUid;
66
91
  readonly items: _angular_core.InputSignal<GogAccordionItem[]>;
67
92
  readonly size: _angular_core.InputSignal<GogSize>;
68
93
  readonly expandFirst: _angular_core.InputSignal<boolean>;
69
94
  readonly multi: _angular_core.InputSignal<boolean>;
70
95
  readonly loading: _angular_core.InputSignal<boolean>;
71
96
  readonly showChevron: _angular_core.InputSignal<boolean>;
97
+ /**
98
+ * When set, wraps each header button in `role="heading"` with this `aria-level`,
99
+ * so screen-reader users navigating by headings can find accordion sections.
100
+ * Left unset by default since not every accordion instance represents document structure
101
+ * (e.g. one nested inside a card).
102
+ */
103
+ readonly headingLevel: _angular_core.InputSignal<4 | 2 | 3 | 5 | 6 | undefined>;
104
+ /**
105
+ * Two-way bindable set of currently open item ids. Exposed as a model so consumers
106
+ * can drive the accordion externally (e.g. `[(openIds)]="mySet"`) instead of only
107
+ * reacting to the `gogToggle` output.
108
+ */
109
+ readonly openIds: _angular_core.ModelSignal<ReadonlySet<string | number>>;
72
110
  readonly gogToggle: _angular_core.OutputEmitterRef<GogAccordionToggleEvent>;
73
111
  readonly headerTpl: _angular_core.Signal<GogAccordionHeaderDirective | undefined>;
74
112
  readonly chevronTpl: _angular_core.Signal<GogAccordionChevronDirective | undefined>;
75
113
  readonly contentTpl: _angular_core.Signal<GogAccordionContentDirective | undefined>;
76
- protected readonly openIds: _angular_core.WritableSignal<Set<string | number>>;
114
+ /**
115
+ * Unique per-instance id prefix. Prevents duplicate DOM ids (and therefore broken
116
+ * aria-controls/aria-labelledby wiring) when several accordions render on the same
117
+ * page and their items happen to share `id` values (e.g. ids coming straight from a DB).
118
+ */
119
+ protected readonly uid: string;
120
+ private readonly host;
121
+ /**
122
+ * Tracks whether the expandFirst auto-open has already run, independently of
123
+ * `openIds` itself. Reading `openIds().size` directly inside the effect would
124
+ * re-subscribe the effect to every future toggle (since `openIds()` gets read
125
+ * on every run once `expandFirst` is true), causing pointless re-evaluation
126
+ * on each click and re-opening the first item if `items` is later replaced
127
+ * with a new array reference after the user closed everything by hand.
128
+ */
129
+ private readonly autoExpanded;
77
130
  constructor();
78
131
  protected isOpen(id: string | number): boolean;
79
132
  protected toggle(item: GogAccordionItem): void;
80
- protected onHeaderKeydown(event: KeyboardEvent, index: number): void;
133
+ protected onHeaderKeydown(event: KeyboardEvent): void;
81
134
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AccordionComponent, never>;
82
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<AccordionComponent, "gog-accordion", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "expandFirst": { "alias": "expandFirst"; "required": false; "isSignal": true; }; "multi": { "alias": "multi"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "gogToggle": "gogToggle"; }, ["headerTpl", "chevronTpl", "contentTpl"], never, true, never>;
135
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AccordionComponent, "gog-accordion", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "expandFirst": { "alias": "expandFirst"; "required": false; "isSignal": true; }; "multi": { "alias": "multi"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; "openIds": { "alias": "openIds"; "required": false; "isSignal": true; }; }, { "openIds": "openIdsChange"; "gogToggle": "gogToggle"; }, ["headerTpl", "chevronTpl", "contentTpl"], never, true, never>;
83
136
  }
84
137
 
85
138
  declare class CheckboxComponent implements ControlValueAccessor {
@@ -89,35 +142,49 @@ declare class CheckboxComponent implements ControlValueAccessor {
89
142
  readonly indeterminate: _angular_core.InputSignal<boolean>;
90
143
  readonly disabled: _angular_core.InputSignal<boolean>;
91
144
  readonly checkIconTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
92
- /** Two-way bindable checked state: `[(checked)]="signal"`. */
145
+ /**
146
+ * Two-way bindable checked state: `[(checked)]="signal"`.
147
+ * This is the same state Angular Forms drives via `writeValue`/`registerOnChange`
148
+ * when the component is used with `formControlName`/`[formControl]`/`ngModel`.
149
+ * Don't wire both a form directive AND `[(checked)]` to the same instance —
150
+ * pick one, otherwise you end up with two competing sources of truth.
151
+ */
93
152
  readonly checked: _angular_core.ModelSignal<boolean>;
94
- private readonly cvaDisabled;
95
- protected readonly isDisabled: _angular_core.Signal<boolean>;
96
153
  protected readonly controlSize: _angular_core.Signal<{
97
- readonly boxSize: "var(--control-checkbox-box-size-sm, 18px)";
98
- readonly labelSize: "var(--control-checkbox-label-size-sm, 0.8125rem)";
99
- readonly indicatorSize: "var(--control-checkbox-icon-size-sm, 12px)";
154
+ readonly boxSize: "var(--gog-control-checkbox-box-size-xsm, 12px)";
155
+ readonly labelSize: "var(--gog-control-checkbox-label-size-xsm, 0.6875rem)";
156
+ readonly indicatorSize: "var(--gog-control-checkbox-icon-size-xsm, 10px)";
157
+ } | {
158
+ readonly boxSize: "var(--gog-control-checkbox-box-size-sm, 18px)";
159
+ readonly labelSize: "var(--gog-control-checkbox-label-size-sm, 0.8125rem)";
160
+ readonly indicatorSize: "var(--gog-control-checkbox-icon-size-sm, 12px)";
161
+ } | {
162
+ readonly boxSize: "var(--gog-control-checkbox-box-size-md, 24px)";
163
+ readonly labelSize: "var(--gog-control-checkbox-label-size-md, 0.9375rem)";
164
+ readonly indicatorSize: "var(--gog-control-checkbox-icon-size-md, 14px)";
100
165
  } | {
101
- readonly boxSize: "var(--control-checkbox-box-size-md, 24px)";
102
- readonly labelSize: "var(--control-checkbox-label-size-md, 0.9375rem)";
103
- readonly indicatorSize: "var(--control-checkbox-icon-size-md, 14px)";
166
+ readonly boxSize: "var(--gog-control-checkbox-box-size-lg, 32px)";
167
+ readonly labelSize: "var(--gog-control-checkbox-label-size-lg, 1.0625rem)";
168
+ readonly indicatorSize: "var(--gog-control-checkbox-icon-size-lg, 18px)";
104
169
  } | {
105
- readonly boxSize: "var(--control-checkbox-box-size-lg, 32px)";
106
- readonly labelSize: "var(--control-checkbox-label-size-lg, 1.0625rem)";
107
- readonly indicatorSize: "var(--control-checkbox-icon-size-lg, 18px)";
170
+ readonly boxSize: "var(--gog-control-checkbox-box-size-slg, 40px)";
171
+ readonly labelSize: "var(--gog-control-checkbox-label-size-slg, 1.1875rem)";
172
+ readonly indicatorSize: "var(--gog-control-checkbox-icon-size-slg, 22px)";
108
173
  }>;
109
- protected readonly boxSize: _angular_core.Signal<"var(--control-checkbox-box-size-sm, 18px)" | "var(--control-checkbox-box-size-md, 24px)" | "var(--control-checkbox-box-size-lg, 32px)">;
110
- protected readonly checkboxPadding = "var(--control-checkbox-padding, 6px)";
111
- protected readonly labelSize: _angular_core.Signal<"var(--control-checkbox-label-size-sm, 0.8125rem)" | "var(--control-checkbox-label-size-md, 0.9375rem)" | "var(--control-checkbox-label-size-lg, 1.0625rem)">;
112
- protected readonly iconSize: _angular_core.Signal<"var(--control-checkbox-icon-size-sm, 12px)" | "var(--control-checkbox-icon-size-md, 14px)" | "var(--control-checkbox-icon-size-lg, 18px)">;
113
- private onCheckedChange;
114
- private onTouched;
174
+ protected readonly boxSize: _angular_core.Signal<"var(--gog-control-checkbox-box-size-xsm, 12px)" | "var(--gog-control-checkbox-box-size-sm, 18px)" | "var(--gog-control-checkbox-box-size-md, 24px)" | "var(--gog-control-checkbox-box-size-lg, 32px)" | "var(--gog-control-checkbox-box-size-slg, 40px)">;
175
+ protected readonly checkboxPadding = "var(--gog-control-checkbox-padding, 6px)";
176
+ protected readonly labelSize: _angular_core.Signal<"var(--gog-control-checkbox-label-size-xsm, 0.6875rem)" | "var(--gog-control-checkbox-label-size-sm, 0.8125rem)" | "var(--gog-control-checkbox-label-size-md, 0.9375rem)" | "var(--gog-control-checkbox-label-size-lg, 1.0625rem)" | "var(--gog-control-checkbox-label-size-slg, 1.1875rem)">;
177
+ protected readonly iconSize: _angular_core.Signal<"var(--gog-control-checkbox-icon-size-xsm, 10px)" | "var(--gog-control-checkbox-icon-size-sm, 12px)" | "var(--gog-control-checkbox-icon-size-md, 14px)" | "var(--gog-control-checkbox-icon-size-lg, 18px)" | "var(--gog-control-checkbox-icon-size-slg, 22px)">;
178
+ private readonly cvaDisabled;
179
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
115
180
  writeValue(val: boolean): void;
116
181
  registerOnChange(fn: (val: boolean) => void): void;
117
182
  registerOnTouched(fn: () => void): void;
118
183
  setDisabledState(isDisabled: boolean): void;
119
184
  onInputChange(event: Event): void;
120
185
  onBlur(): void;
186
+ private onCheckedChange;
187
+ private onTouched;
121
188
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<CheckboxComponent, never>;
122
189
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<CheckboxComponent, "gog-checkbox", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "checkIconTemplate": { "alias": "checkIconTemplate"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; }, never, never, true, never>;
123
190
  }
@@ -139,13 +206,17 @@ declare class ConfirmationDialogComponent {
139
206
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfirmationDialogComponent, "gog-confirmation-dialog", never, {}, {}, never, never, true, never>;
140
207
  }
141
208
 
142
- type GogIconName = 'check' | 'close' | 'chevron-down' | 'chevron-up' | 'sort' | 'sort-up' | 'sort-down' | 'success' | 'error' | 'warning' | 'info';
209
+ type GogIconName = 'check' | 'close' | 'chevron-up' | 'chevron-down' | 'sort' | 'sort-up' | 'sort-down' | 'success' | 'error' | 'warning' | 'info' | 'checkbox' | 'checkbox-checked' | 'eye' | 'eye-off';
210
+ declare const ICON_DEFS: Record<GogIconName, string>;
211
+
143
212
  declare class IconComponent {
213
+ private readonly sanitizer;
144
214
  readonly name: _angular_core.InputSignal<GogIconName>;
145
215
  readonly template: _angular_core.InputSignal<TemplateRef<unknown> | null>;
146
216
  readonly title: _angular_core.InputSignal<string>;
147
217
  readonly ariaHidden: _angular_core.InputSignal<boolean>;
148
218
  protected readonly ariaLabel: _angular_core.Signal<string | null>;
219
+ protected readonly iconSvg: _angular_core.Signal<_angular_platform_browser.SafeHtml>;
149
220
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
150
221
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "gog-icon", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "template": { "alias": "template"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "ariaHidden": { "alias": "ariaHidden"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
151
222
  }
@@ -332,13 +403,27 @@ declare class ToastContainerComponent {
332
403
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ToastContainerComponent, "gog-toast-container", never, { "maxVisiblePerPosition": { "alias": "maxVisiblePerPosition"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
333
404
  }
334
405
 
335
- declare class InputfieldComponent implements ControlValueAccessor {
406
+ /**
407
+ * `'manual'` (default): the field shows `errorMessage` for as long as it is non-empty — the
408
+ * consumer decides when to clear it, e.g.
409
+ * `errorMessage="control.invalid && control.touched ? 'Required' : ''"`.
410
+ *
411
+ * `'auto'`: shown once the attached form control has been touched and is invalid — the
412
+ * consumer only supplies the message text, not the timing. Requires a
413
+ * `[formControl]` / `formControlName` / `ngModel` on the element; without one this falls
414
+ * back to `'manual'`, since there is no control state to key off.
415
+ */
416
+ type GogErrorDisplay = 'auto' | 'manual';
417
+
418
+ declare class InputfieldComponent implements ControlValueAccessor, DoCheck {
336
419
  readonly label: _angular_core.InputSignal<string>;
337
420
  readonly placeholder: _angular_core.InputSignal<string>;
338
421
  readonly type: _angular_core.InputSignal<"text" | "password" | "email">;
339
422
  /** Defaults to 'current-password' for password fields, 'off' otherwise */
340
423
  readonly autocomplete: _angular_core.InputSignal<string>;
341
424
  readonly errorMessage: _angular_core.InputSignal<string>;
425
+ /** See `GogErrorDisplay`. Defaults to `'manual'`, matching every other control in the library. */
426
+ readonly errorDisplay: _angular_core.InputSignal<GogErrorDisplay>;
342
427
  readonly name: _angular_core.InputSignal<string>;
343
428
  readonly inputId: _angular_core.InputSignal<string>;
344
429
  readonly disabled: _angular_core.InputSignal<boolean>;
@@ -359,18 +444,33 @@ declare class InputfieldComponent implements ControlValueAccessor {
359
444
  readonly iconStartLabel: _angular_core.InputSignal<string>;
360
445
  /** aria-label for the end icon button (required when iconEndFn is set) */
361
446
  readonly iconEndLabel: _angular_core.InputSignal<string>;
447
+ /** aria-label for the reveal-password button, shown when `type` is `'password'` */
448
+ readonly showPasswordLabel: _angular_core.InputSignal<string>;
449
+ /** aria-label for the hide-password button, shown once the password is revealed */
450
+ readonly hidePasswordLabel: _angular_core.InputSignal<string>;
362
451
  /** Two-way bindable value: `[(value)]="signal"` or `[value]` / `(valueChange)`. */
363
452
  readonly value: _angular_core.ModelSignal<string>;
453
+ private readonly ngControl;
364
454
  private readonly cvaDisabled;
455
+ private readonly errorState;
456
+ private readonly passwordVisible;
365
457
  protected readonly isDisabled: _angular_core.Signal<boolean>;
458
+ protected readonly isPasswordField: _angular_core.Signal<boolean>;
459
+ protected readonly effectiveType: _angular_core.Signal<"text" | "password" | "email">;
366
460
  protected readonly effectiveAutocomplete: _angular_core.Signal<string>;
367
461
  protected readonly hasError: _angular_core.Signal<boolean>;
462
+ protected readonly visibleError: _angular_core.Signal<string>;
368
463
  protected readonly hasIconStart: _angular_core.Signal<boolean>;
369
- protected readonly hasIconEnd: _angular_core.Signal<boolean>;
370
464
  protected readonly hasIconStartAction: _angular_core.Signal<boolean>;
465
+ /** For password fields the trailing icon is always the built-in show/hide toggle. */
466
+ protected readonly effectiveIconEnd: _angular_core.Signal<"" | GogIconName>;
467
+ protected readonly effectiveIconEndLabel: _angular_core.Signal<string>;
468
+ protected readonly hasIconEnd: _angular_core.Signal<boolean>;
371
469
  protected readonly hasIconEndAction: _angular_core.Signal<boolean>;
372
470
  private _onChange;
373
471
  private _onTouched;
472
+ constructor();
473
+ ngDoCheck(): void;
374
474
  writeValue(val: string): void;
375
475
  registerOnChange(fn: (val: string) => void): void;
376
476
  registerOnTouched(fn: () => void): void;
@@ -380,7 +480,7 @@ declare class InputfieldComponent implements ControlValueAccessor {
380
480
  onInput(event: Event): void;
381
481
  onBlur(): void;
382
482
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<InputfieldComponent, never>;
383
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<InputfieldComponent, "gog-inputfield", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "iconStart": { "alias": "iconStart"; "required": false; "isSignal": true; }; "iconEnd": { "alias": "iconEnd"; "required": false; "isSignal": true; }; "iconStartTemplate": { "alias": "iconStartTemplate"; "required": false; "isSignal": true; }; "iconEndTemplate": { "alias": "iconEndTemplate"; "required": false; "isSignal": true; }; "iconStartFn": { "alias": "iconStartFn"; "required": false; "isSignal": true; }; "iconEndFn": { "alias": "iconEndFn"; "required": false; "isSignal": true; }; "iconStartLabel": { "alias": "iconStartLabel"; "required": false; "isSignal": true; }; "iconEndLabel": { "alias": "iconEndLabel"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
483
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<InputfieldComponent, "gog-inputfield", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "errorDisplay": { "alias": "errorDisplay"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "iconStart": { "alias": "iconStart"; "required": false; "isSignal": true; }; "iconEnd": { "alias": "iconEnd"; "required": false; "isSignal": true; }; "iconStartTemplate": { "alias": "iconStartTemplate"; "required": false; "isSignal": true; }; "iconEndTemplate": { "alias": "iconEndTemplate"; "required": false; "isSignal": true; }; "iconStartFn": { "alias": "iconStartFn"; "required": false; "isSignal": true; }; "iconEndFn": { "alias": "iconEndFn"; "required": false; "isSignal": true; }; "iconStartLabel": { "alias": "iconStartLabel"; "required": false; "isSignal": true; }; "iconEndLabel": { "alias": "iconEndLabel"; "required": false; "isSignal": true; }; "showPasswordLabel": { "alias": "showPasswordLabel"; "required": false; "isSignal": true; }; "hidePasswordLabel": { "alias": "hidePasswordLabel"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
384
484
  }
385
485
 
386
486
  declare class ChipComponent {
@@ -412,157 +512,241 @@ declare class TagComponent {
412
512
  readonly iconName: _angular_core.InputSignal<GogIconName | null>;
413
513
  readonly iconTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
414
514
  protected readonly hasIcon: _angular_core.Signal<boolean>;
515
+ protected readonly hostClasses: _angular_core.Signal<string>;
415
516
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TagComponent, never>;
416
517
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TagComponent, "gog-tag", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "shape": { "alias": "shape"; "required": false; "isSignal": true; }; "iconName": { "alias": "iconName"; "required": false; "isSignal": true; }; "iconTemplate": { "alias": "iconTemplate"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
417
518
  }
418
519
 
419
520
  type GogDropdownDirection = 'auto' | 'up' | 'down';
521
+ interface GogDropdownPlacement {
522
+ direction: 'up' | 'down';
523
+ top: number;
524
+ left: number;
525
+ width: number;
526
+ maxHeight: number;
527
+ }
420
528
 
421
- interface GogSelectOption {
529
+ /** A single choice in any of the listbox-style controls (`gog-select`, `gog-multiselect`). */
530
+ interface GogDropdownOption {
422
531
  id: string | number;
423
532
  name: string;
424
533
  disabled?: boolean;
425
534
  }
426
- declare class SelectComponent implements ControlValueAccessor {
427
- private static nextId;
428
- private readonly generatedId;
429
- private readonly generatedListboxId;
430
- readonly inputId: _angular_core.InputSignal<string>;
535
+ /**
536
+ * Shared behaviour for the listbox-style controls: open/close, placement, the
537
+ * append-to-body overlay, click-outside, keyboard navigation and `ControlValueAccessor`
538
+ * plumbing. Subclasses supply only what actually differs — the value type, the panel
539
+ * markup, and the BEM class names used to find the trigger and the options.
540
+ *
541
+ * Exported because it appears in the public type signatures of the components that
542
+ * extend it; it is not meant to be used or subclassed by consumers.
543
+ */
544
+ declare abstract class GogDropdownBase<TValue> implements ControlValueAccessor, DoCheck {
545
+ private static nextUid;
431
546
  readonly label: _angular_core.InputSignal<string>;
432
547
  readonly ariaLabel: _angular_core.InputSignal<string>;
433
548
  readonly placeholder: _angular_core.InputSignal<string>;
434
- readonly options: _angular_core.InputSignal<GogSelectOption[]>;
549
+ readonly options: _angular_core.InputSignal<GogDropdownOption[]>;
435
550
  readonly errorMessage: _angular_core.InputSignal<string>;
551
+ /** See `GogErrorDisplay`. Defaults to `'manual'`, matching every other control in the library. */
552
+ readonly errorDisplay: _angular_core.InputSignal<GogErrorDisplay>;
553
+ readonly size: _angular_core.InputSignal<GogSize>;
436
554
  readonly dropdownDirection: _angular_core.InputSignal<GogDropdownDirection>;
555
+ /**
556
+ * Explicit stacking order for the panel. Left unset the panel falls back to the
557
+ * stylesheet's `--gog-dropdown-z`, so the default lives in CSS where a consumer can
558
+ * retheme it, rather than being baked into the component.
559
+ */
437
560
  readonly dropdownZIndex: _angular_core.InputSignal<number | null>;
561
+ /**
562
+ * Fixed panel width as any CSS length (`'320px'`, `'40ch'`, `'100%'`, …), applied only
563
+ * when `appendToBody` is set. Left unset the panel matches the trigger's width, same as
564
+ * the inline panel already does via CSS.
565
+ */
566
+ readonly dropdownWidth: _angular_core.InputSignal<string | null>;
567
+ /**
568
+ * Fixed panel max-height as any CSS length, applied only when `appendToBody` is set.
569
+ * `px`, `%` and `vh` also feed the up/down placement math (see `resolveCssLengthPx`); any
570
+ * other unit still renders correctly but is invisible to that heuristic, so the panel may
571
+ * pick the "wrong" side close to a viewport edge. Left unset the panel keeps the existing
572
+ * viewport-derived, auto-flipping height.
573
+ */
574
+ readonly dropdownMaxHeight: _angular_core.InputSignal<string | null>;
438
575
  readonly appendToBody: _angular_core.InputSignal<boolean>;
439
576
  readonly disabled: _angular_core.InputSignal<boolean>;
440
577
  readonly chevronTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
441
- /** Two-way bindable selected value: `[(value)]="signal"`. */
442
- readonly value: _angular_core.ModelSignal<string | number | null>;
443
578
  readonly isOpen: _angular_core.WritableSignal<boolean>;
444
- private readonly cvaDisabled;
445
- protected readonly dropdownDirectionState: _angular_core.WritableSignal<"up" | "down">;
446
- private readonly elRef;
579
+ /** The `<ng-template>` holding the panel markup, rendered inline or into `<body>`. */
580
+ protected abstract readonly panelTemplate: Signal<TemplateRef<unknown> | undefined>;
581
+ /** Declared by the subclass so each control keeps its own value type. */
582
+ protected abstract readonly value: ModelSignal<TValue>;
583
+ /** Value applied when a form writes `null` / the control is reset. */
584
+ protected abstract readonly emptyValue: TValue;
585
+ /** BEM class of one option button, used to collect keyboard-navigable elements. */
586
+ protected abstract readonly optionClass: string;
587
+ /** BEM class of the focusable trigger. */
588
+ protected abstract readonly triggerClass: string;
589
+ /**
590
+ * Spacing tokens feeding the height estimate. Overridable so each control keeps the
591
+ * `--gog-<block>-*` names it already exposes to consumers for theming.
592
+ */
593
+ protected readonly optionGapToken: string;
594
+ protected readonly optionsPaddingToken: string;
595
+ /** Keep in sync with the real `max-height` on the subclass's `__dropdown` block. */
596
+ protected readonly panelMaxHeightToken: string;
597
+ /** Estimated row height fed into the placement math; not a real layout property. */
598
+ protected readonly optionHeightToken: string;
599
+ /** Unique per-instance suffix, so several dropdowns on a page can't collide on DOM ids. */
600
+ protected readonly uid: number;
601
+ protected readonly elRef: ElementRef<any>;
602
+ protected readonly isBrowser: boolean;
603
+ private readonly document;
447
604
  private readonly appRef;
448
- private readonly envInjector;
449
605
  private readonly destroyRef;
450
- private readonly isBrowser;
451
- protected readonly triggerId: _angular_core.Signal<string>;
452
- protected readonly listboxId: _angular_core.Signal<string>;
453
- protected readonly isDisabled: _angular_core.Signal<boolean>;
454
- protected readonly selectedOption: _angular_core.Signal<GogSelectOption | null>;
455
- protected readonly hasError: _angular_core.Signal<boolean>;
456
- protected readonly errorId: _angular_core.Signal<string | null>;
457
- private portalHost;
458
- private portalRef;
459
- private onChange;
460
- private onTouched;
606
+ private readonly ngControl;
607
+ private readonly overlay;
608
+ private readonly cvaDisabled;
609
+ private readonly errorState;
610
+ protected readonly isDisabled: Signal<boolean>;
611
+ protected readonly dropdownDirectionState: _angular_core.WritableSignal<"up" | "down">;
612
+ protected readonly panelPlacement: _angular_core.WritableSignal<GogDropdownPlacement | null>;
613
+ /**
614
+ * Stacking order to write onto the panel, or null to leave it to the stylesheet.
615
+ *
616
+ * Only needed when appending to `<body>`: an inline panel inherits `--gog-dropdown-z` from
617
+ * its surroundings — which is how a dropdown inside a dialog ends up above the dialog —
618
+ * but an appended one sits outside that subtree and inherits nothing, so the value has
619
+ * to be resolved from the trigger and written out explicitly.
620
+ */
621
+ protected readonly panelZIndex: _angular_core.WritableSignal<number | null>;
622
+ /** `dropdownWidth`, or the trigger-derived width from `panelPlacement`, as a CSS value. */
623
+ protected readonly resolvedPanelWidth: Signal<string | null>;
624
+ /** `dropdownMaxHeight`, or the viewport-derived max-height from `panelPlacement`. */
625
+ protected readonly resolvedPanelMaxHeight: Signal<string | null>;
626
+ protected readonly hasError: Signal<boolean>;
627
+ protected readonly visibleError: Signal<string>;
628
+ /** Measured once per open rather than per scroll tick — see `refreshPanelMetrics`. */
629
+ private optionGap;
630
+ private optionsPadding;
631
+ private maxPanelHeight;
632
+ private optionHeight;
633
+ private repositionFrame;
634
+ private onChangeFn;
635
+ private onTouchedFn;
461
636
  constructor();
462
- writeValue(val: string | number | null): void;
463
- registerOnChange(fn: (val: string | number | null) => void): void;
637
+ /**
638
+ * Binds the click-outside and reposition listeners only for as long as the panel is
639
+ * open. Bound permanently — as host listeners were — every dropdown on the page runs a
640
+ * handler on every document click and every scroll frame, whether or not it is showing
641
+ * anything.
642
+ */
643
+ private bindWhileOpen;
644
+ ngDoCheck(): void;
645
+ writeValue(val: TValue | null): void;
646
+ registerOnChange(fn: (val: TValue) => void): void;
464
647
  registerOnTouched(fn: () => void): void;
465
648
  setDisabledState(isDisabled: boolean): void;
466
649
  protected toggle(): void;
650
+ protected open(): void;
467
651
  protected close(): void;
468
- protected onDocumentClick(event: MouseEvent): void;
469
- protected onScrollOrResize(): void;
470
- protected selectOption(option: GogSelectOption, event: MouseEvent): void;
471
- private openDropdown;
652
+ /** Writes a new selection out to both the model and the attached form control. */
653
+ protected commitValue(next: TValue): void;
654
+ protected markTouched(): void;
655
+ private closeIfClickedOutside;
656
+ /**
657
+ * Coalesces bursts of scroll/resize events into one reposition per frame. Placement
658
+ * reads layout, so running it per event is what makes a scroll janky.
659
+ */
660
+ private scheduleReposition;
661
+ /** Jumps from the trigger into the option list on ArrowDown/ArrowUp while open. */
662
+ protected onTriggerArrowKeydown(event: Event): void;
663
+ protected onOptionKeydown(event: KeyboardEvent): void;
664
+ protected focusTrigger(): void;
665
+ /** Extra chrome stacked above the options (e.g. a select-all row), in px. */
666
+ protected extraPanelHeight(): number;
667
+ private enabledOptionElements;
668
+ private attachOverlay;
669
+ /**
670
+ * Reads the spacing tokens that feed the height estimate. Done once per open instead of
671
+ * on every scroll tick, because `getComputedStyle` forces a style recalculation and the
672
+ * tokens cannot change while the panel is on screen.
673
+ */
674
+ private refreshPanelMetrics;
675
+ /**
676
+ * Rough height, used only to choose up/down and to cap `max-height` before the panel
677
+ * has been laid out. Deliberately an estimate: measuring would require rendering the
678
+ * panel first, which is what we are trying to position. A resolvable `dropdownMaxHeight`
679
+ * replaces the row-count guess outright, since it is exact rather than estimated.
680
+ */
472
681
  private estimatePanelHeight;
473
- private updateInlineDirection;
474
- private openPortal;
475
- private updatePortalPosition;
476
- private destroyPortal;
477
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SelectComponent, never>;
478
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SelectComponent, "gog-select", never, { "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "dropdownDirection": { "alias": "dropdownDirection"; "required": false; "isSignal": true; }; "dropdownZIndex": { "alias": "dropdownZIndex"; "required": false; "isSignal": true; }; "appendToBody": { "alias": "appendToBody"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "chevronTemplate": { "alias": "chevronTemplate"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
682
+ /**
683
+ * The trigger's own rect, not the whole component's — a label above it or an error
684
+ * message below it sit in normal document flow and are not part of what the panel needs
685
+ * to clear. This also keeps `appendToBody` placement consistent with the inline panel,
686
+ * which is already positioned purely relative to the trigger via CSS.
687
+ */
688
+ private triggerRect;
689
+ /** The stacking order the panel would have had if it were still inside the subtree. */
690
+ private resolvePanelZIndex;
691
+ private updatePlacement;
692
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<GogDropdownBase<any>, never>;
693
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<GogDropdownBase<any>, never, never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "errorDisplay": { "alias": "errorDisplay"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "dropdownDirection": { "alias": "dropdownDirection"; "required": false; "isSignal": true; }; "dropdownZIndex": { "alias": "dropdownZIndex"; "required": false; "isSignal": true; }; "dropdownWidth": { "alias": "dropdownWidth"; "required": false; "isSignal": true; }; "dropdownMaxHeight": { "alias": "dropdownMaxHeight"; "required": false; "isSignal": true; }; "appendToBody": { "alias": "appendToBody"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "chevronTemplate": { "alias": "chevronTemplate"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
479
694
  }
480
695
 
481
- interface GogMultiselectOption {
482
- id: string | number;
483
- name: string;
696
+ /** @deprecated Prefer `GogDropdownOption`; kept as an alias so existing imports keep working. */
697
+ type GogSelectOption = GogDropdownOption;
698
+ declare class SelectComponent extends GogDropdownBase<string | number | null> {
699
+ readonly inputId: _angular_core.InputSignal<string>;
700
+ /** Two-way bindable selected value: `[(value)]="signal"`. */
701
+ readonly value: _angular_core.ModelSignal<string | number | null>;
702
+ protected readonly panelTemplate: _angular_core.Signal<TemplateRef<unknown> | undefined>;
703
+ protected readonly emptyValue: null;
704
+ protected readonly optionClass = "gog-select__option";
705
+ protected readonly triggerClass = "gog-select__control";
706
+ protected readonly optionGapToken = "--gog-select-option-gap";
707
+ protected readonly panelMaxHeightToken = "--gog-select-panel-max-height";
708
+ protected readonly optionHeightToken = "--gog-select-option-height";
709
+ protected readonly triggerId: _angular_core.Signal<string>;
710
+ protected readonly listboxId: _angular_core.Signal<string>;
711
+ protected readonly labelId: _angular_core.Signal<string>;
712
+ protected readonly errorId: _angular_core.Signal<string | null>;
713
+ protected readonly selectedOption: _angular_core.Signal<GogDropdownOption | null>;
714
+ protected isSelected(id: string | number): boolean;
715
+ protected selectOption(option: GogDropdownOption, event: MouseEvent): void;
716
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SelectComponent, never>;
717
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SelectComponent, "gog-select", never, { "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
484
718
  }
485
- declare class GogMultiselectDropdownPortal {
486
- top: number;
487
- left: number;
488
- width: number;
489
- maxHeight: number;
490
- zIndex: number;
491
- listboxId: string;
492
- direction: 'up' | 'down';
493
- options: GogMultiselectOption[];
494
- selectedIds: (string | number)[];
495
- showControls: boolean;
496
- onToggle: (o: GogMultiselectOption, e: MouseEvent) => void;
497
- onSelectAll: (e: MouseEvent) => void;
498
- onClearAll: (e: MouseEvent) => void;
499
- isSelected(id: string | number): boolean;
500
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<GogMultiselectDropdownPortal, never>;
501
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<GogMultiselectDropdownPortal, "gog-multiselect-dropdown-portal", never, {}, {}, never, never, true, never>;
502
- }
503
- declare class MultiselectComponent implements ControlValueAccessor {
504
- private static nextId;
505
- protected readonly instanceId: number;
506
- readonly label: _angular_core.InputSignal<string>;
507
- readonly ariaLabel: _angular_core.InputSignal<string>;
508
- readonly placeholder: _angular_core.InputSignal<string>;
509
- readonly options: _angular_core.InputSignal<GogMultiselectOption[]>;
510
- readonly errorMessage: _angular_core.InputSignal<string>;
719
+
720
+ /** @deprecated Prefer `GogDropdownOption`; kept as an alias so existing imports keep working. */
721
+ type GogMultiselectOption = GogDropdownOption;
722
+ declare class MultiselectComponent extends GogDropdownBase<(string | number)[]> {
511
723
  readonly showControls: _angular_core.InputSignal<boolean>;
512
- readonly dropdownDirection: _angular_core.InputSignal<GogDropdownDirection>;
513
- readonly dropdownZIndex: _angular_core.InputSignal<number | null>;
514
- readonly appendToBody: _angular_core.InputSignal<boolean>;
515
- readonly disabled: _angular_core.InputSignal<boolean>;
516
- readonly chevronTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
724
+ /** Where the "select all"/"clear" row sits relative to the option list. Sticky either way. */
725
+ readonly controlsPosition: _angular_core.InputSignal<"top" | "bottom">;
517
726
  readonly clearIconTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
518
727
  /** Two-way bindable selected ids: `[(value)]="signal"`. */
519
728
  readonly value: _angular_core.ModelSignal<(string | number)[]>;
520
- readonly isOpen: _angular_core.WritableSignal<boolean>;
521
- private readonly cvaDisabled;
522
- protected readonly isDisabled: Signal<boolean>;
523
- protected readonly dropdownDirectionState: _angular_core.WritableSignal<"up" | "down">;
524
- private readonly elRef;
525
- private readonly appRef;
526
- private readonly envInjector;
527
- private readonly destroyRef;
528
- private readonly isBrowser;
529
- private readonly ngControl;
530
- private readonly _touched;
531
- private readonly formStatus;
532
- protected readonly hasError: Signal<boolean>;
533
- protected readonly visibleError: Signal<string>;
534
- private portalHost;
535
- private portalRef;
536
- readonly selectedNames: Signal<string>;
537
- private _onChange;
538
- private _onTouched;
539
- constructor();
540
- onDocumentClick(e: MouseEvent): void;
541
- onScrollOrResize(): void;
542
- writeValue(val: (string | number)[] | null): void;
543
- registerOnChange(fn: (val: (string | number)[]) => void): void;
544
- registerOnTouched(fn: () => void): void;
545
- setDisabledState(isDisabled: boolean): void;
729
+ protected readonly panelTemplate: _angular_core.Signal<TemplateRef<unknown> | undefined>;
730
+ protected readonly emptyValue: (string | number)[];
731
+ protected readonly optionClass = "gog-ms__option";
732
+ protected readonly triggerClass = "gog-ms";
733
+ protected readonly optionGapToken = "--gog-ms-option-gap";
734
+ protected readonly optionsPaddingToken = "--gog-ms-options-padding";
735
+ protected readonly panelMaxHeightToken = "--gog-ms-panel-max-height";
736
+ protected readonly optionHeightToken = "--gog-ms-option-height";
737
+ protected readonly listboxId: _angular_core.Signal<string>;
738
+ protected readonly labelId: _angular_core.Signal<string>;
739
+ readonly selectedNames: _angular_core.Signal<string>;
546
740
  protected isSelected(id: string | number): boolean;
547
- protected toggle(): void;
548
- protected toggleOption(option: GogMultiselectOption, e: MouseEvent): void;
549
- private applyToggle;
550
- protected selectAll(e: MouseEvent): void;
551
- protected clearAll(e: MouseEvent): void;
552
- protected clearTrigger(e: Event): void;
553
- protected close(): void;
554
- private estimatePanelHeight;
555
- private getOptionGap;
556
- private getOptionPadding;
557
- private updateInlineDirection;
558
- private openPortal;
559
- private updatePortalPosition;
560
- private destroyPortal;
741
+ protected toggleOption(option: GogDropdownOption, event: MouseEvent): void;
742
+ protected selectAll(event: MouseEvent): void;
743
+ protected clearAll(event: Event): void;
744
+ protected extraPanelHeight(): number;
561
745
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MultiselectComponent, never>;
562
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MultiselectComponent, "gog-multiselect", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "showControls": { "alias": "showControls"; "required": false; "isSignal": true; }; "dropdownDirection": { "alias": "dropdownDirection"; "required": false; "isSignal": true; }; "dropdownZIndex": { "alias": "dropdownZIndex"; "required": false; "isSignal": true; }; "appendToBody": { "alias": "appendToBody"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "chevronTemplate": { "alias": "chevronTemplate"; "required": false; "isSignal": true; }; "clearIconTemplate": { "alias": "clearIconTemplate"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
746
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MultiselectComponent, "gog-multiselect", never, { "showControls": { "alias": "showControls"; "required": false; "isSignal": true; }; "controlsPosition": { "alias": "controlsPosition"; "required": false; "isSignal": true; }; "clearIconTemplate": { "alias": "clearIconTemplate"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
563
747
  }
564
748
 
565
- declare class SliderComponent implements ControlValueAccessor {
749
+ declare class SliderComponent implements ControlValueAccessor, DoCheck {
566
750
  private static nextId;
567
751
  protected readonly inputId: string;
568
752
  readonly label: _angular_core.InputSignal<string>;
@@ -572,19 +756,27 @@ declare class SliderComponent implements ControlValueAccessor {
572
756
  readonly showValue: _angular_core.InputSignal<boolean>;
573
757
  readonly showThumb: _angular_core.InputSignal<boolean>;
574
758
  readonly errorMessage: _angular_core.InputSignal<string>;
759
+ /** See `GogErrorDisplay`. Defaults to `'manual'`, matching every other control in the library. */
760
+ readonly errorDisplay: _angular_core.InputSignal<GogErrorDisplay>;
575
761
  readonly ariaLabel: _angular_core.InputSignal<string>;
576
762
  readonly disabled: _angular_core.InputSignal<boolean>;
577
763
  /** Two-way bindable value: `[(value)]="signal"`. */
578
764
  readonly value: _angular_core.ModelSignal<number>;
765
+ private readonly ngControl;
579
766
  private readonly cvaDisabled;
767
+ private readonly errorState;
580
768
  protected readonly isDisabled: _angular_core.Signal<boolean>;
581
769
  protected readonly clampedValue: _angular_core.Signal<number>;
582
770
  protected readonly fillPercent: _angular_core.Signal<number>;
583
771
  protected readonly thumbPos: _angular_core.Signal<string>;
584
772
  protected readonly fillScale: _angular_core.Signal<number>;
773
+ protected readonly hasError: _angular_core.Signal<boolean>;
774
+ protected readonly visibleError: _angular_core.Signal<string>;
585
775
  protected readonly errorId: _angular_core.Signal<string | null>;
586
776
  private onChange;
587
777
  private onTouched;
778
+ constructor();
779
+ ngDoCheck(): void;
588
780
  writeValue(val: number): void;
589
781
  registerOnChange(fn: (val: number) => void): void;
590
782
  registerOnTouched(fn: () => void): void;
@@ -592,19 +784,78 @@ declare class SliderComponent implements ControlValueAccessor {
592
784
  onInput(event: Event): void;
593
785
  onBlur(): void;
594
786
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SliderComponent, never>;
595
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SliderComponent, "gog-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "showThumb": { "alias": "showThumb"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
787
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SliderComponent, "gog-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "showThumb": { "alias": "showThumb"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "errorDisplay": { "alias": "errorDisplay"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
788
+ }
789
+
790
+ declare class SkeletonComponent {
791
+ readonly shape: _angular_core.InputSignal<GogSkeletonShape>;
792
+ readonly size: _angular_core.InputSignal<GogSize>;
793
+ readonly animation: _angular_core.InputSignal<GogSkeletonAnimation>;
794
+ /** CSS width, e.g. '240px' or '60%'. Falls back to a shape/size default when unset. */
795
+ readonly width: _angular_core.InputSignal<string | null>;
796
+ /** CSS height override. Ignored for `text`, whose lines size from `size` instead. */
797
+ readonly height: _angular_core.InputSignal<string | null>;
798
+ /** Number of stacked lines when `shape="text"`. The last line renders shorter. */
799
+ readonly lines: _angular_core.InputSignal<number>;
800
+ readonly rounded: _angular_core.InputSignal<boolean>;
801
+ readonly ariaLabel: _angular_core.InputSignal<string | null>;
802
+ protected readonly lineList: _angular_core.Signal<boolean[]>;
803
+ protected readonly resolvedHeight: _angular_core.Signal<string | null>;
804
+ protected readonly hostClasses: _angular_core.Signal<string>;
805
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonComponent, never>;
806
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonComponent, "gog-skeleton", never, { "shape": { "alias": "shape"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "animation": { "alias": "animation"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "lines": { "alias": "lines"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
807
+ }
808
+
809
+ declare class PaginatorComponent {
810
+ /** 1-based current page. Two-way bindable: `[(page)]="myPageSignal"`. */
811
+ readonly page: _angular_core.ModelSignal<number>;
812
+ readonly totalPages: _angular_core.InputSignal<number>;
813
+ /**
814
+ * `window` (default): a fixed number of page buttons (`visiblePages`) that slides to keep
815
+ * the current page centered, clamped at the edges — no ellipsis, no pinned boundaries
816
+ * unless `showFirstPage`/`showLastPage` ask for them.
817
+ * `ellipsis`: the original behavior — first and last page are always pinned, and
818
+ * `siblingCount` pages are kept around the current one, with a "…" filling the gap. Kept
819
+ * around as an opt-in for consumers (like `gog-table`) already built around that look.
820
+ */
821
+ readonly rangeMode: _angular_core.InputSignal<GogPaginatorRangeMode>;
822
+ /** `rangeMode="window"` only: how many page number buttons stay visible at once. */
823
+ readonly visiblePages: _angular_core.InputSignal<number>;
824
+ /** `rangeMode="window"` only: always keep page 1 reachable, with a "…" if it's not adjacent. */
825
+ readonly showFirstPage: _angular_core.InputSignal<boolean>;
826
+ /** `rangeMode="window"` only: always keep the last page reachable, with a "…" if it's not adjacent. */
827
+ readonly showLastPage: _angular_core.InputSignal<boolean>;
828
+ /** `rangeMode="ellipsis"` only: how many page numbers to keep on each side of the current page. */
829
+ readonly siblingCount: _angular_core.InputSignal<number>;
830
+ readonly size: _angular_core.InputSignal<GogSize>;
831
+ readonly disabled: _angular_core.InputSignal<boolean>;
832
+ readonly ariaLabel: _angular_core.InputSignal<string>;
833
+ protected readonly pageNumbers: _angular_core.Signal<(number | "...")[]>;
834
+ constructor();
835
+ private windowRange;
836
+ private ellipsisRange;
837
+ protected isNumber(value: number | '...'): value is number;
838
+ protected goTo(target: number): void;
839
+ protected prev(): void;
840
+ protected next(): void;
841
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PaginatorComponent, never>;
842
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PaginatorComponent, "gog-paginator", never, { "page": { "alias": "page"; "required": false; "isSignal": true; }; "totalPages": { "alias": "totalPages"; "required": false; "isSignal": true; }; "rangeMode": { "alias": "rangeMode"; "required": false; "isSignal": true; }; "visiblePages": { "alias": "visiblePages"; "required": false; "isSignal": true; }; "showFirstPage": { "alias": "showFirstPage"; "required": false; "isSignal": true; }; "showLastPage": { "alias": "showLastPage"; "required": false; "isSignal": true; }; "siblingCount": { "alias": "siblingCount"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "page": "pageChange"; }, never, never, true, never>;
596
843
  }
597
844
 
598
845
  declare class SpinnerOverlayComponent {
599
846
  readonly loading: _angular_core.InputSignal<boolean>;
600
847
  readonly size: _angular_core.InputSignal<GogSize>;
601
848
  readonly ariaLabel: _angular_core.InputSignal<string>;
849
+ readonly variant: _angular_core.InputSignal<GogSpinnerVariant>;
602
850
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpinnerOverlayComponent, never>;
603
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpinnerOverlayComponent, "gog-spinner-overlay", never, { "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
851
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpinnerOverlayComponent, "gog-spinner-overlay", never, { "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
604
852
  }
605
853
 
606
- declare class Column<T = unknown> {
607
- readonly field: _angular_core.InputSignal<keyof T & string>;
854
+ /** Default comparator: locale-aware for strings via `Intl.Collator`, `<`/`>` otherwise. */
855
+ declare function defaultCompare(a: unknown, b: unknown): number;
856
+ declare class Column {
857
+ /** Field name, or a dot-path into a nested property (e.g. `"address.city"`). */
858
+ readonly field: _angular_core.InputSignal<string>;
608
859
  readonly header: _angular_core.InputSignal<string>;
609
860
  readonly sortable: _angular_core.InputSignal<boolean>;
610
861
  /** Fixed width, e.g. "120px" or "20%" */
@@ -613,8 +864,10 @@ declare class Column<T = unknown> {
613
864
  readonly minWidth: _angular_core.InputSignal<string>;
614
865
  /** Max width, e.g. "300px" */
615
866
  readonly maxWidth: _angular_core.InputSignal<string>;
616
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<Column<any>, never>;
617
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Column<any>, "column", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "sortable": { "alias": "sortable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "maxWidth": { "alias": "maxWidth"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
867
+ /** Custom sort comparator for this column. Defaults to `defaultCompare`. */
868
+ readonly comparator: _angular_core.InputSignal<((a: unknown, b: unknown) => number) | null>;
869
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<Column, never>;
870
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Column, "column", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "sortable": { "alias": "sortable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "maxWidth": { "alias": "maxWidth"; "required": false; "isSignal": true; }; "comparator": { "alias": "comparator"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
618
871
  }
619
872
 
620
873
  interface GogTableBodyContext<T> {
@@ -664,27 +917,28 @@ declare class TableComponent<T extends object> {
664
917
  readonly stickyHeader: _angular_core.InputSignal<boolean>;
665
918
  /** Row density: lg (default) / md (compact) / sm (dense) */
666
919
  readonly size: _angular_core.InputSignal<GogSize>;
667
- readonly columns: _angular_core.Signal<readonly Column<any>[]>;
920
+ readonly columns: _angular_core.Signal<readonly Column[]>;
668
921
  readonly templates: _angular_core.Signal<readonly TemplateDirective[]>;
669
- readonly currentPage: _angular_core.WritableSignal<number>;
670
922
  readonly sortState: _angular_core.WritableSignal<SortState>;
671
- constructor();
672
923
  readonly sortedData: _angular_core.Signal<T[]>;
673
924
  readonly totalPages: _angular_core.Signal<number>;
925
+ /**
926
+ * Resets to page 1 whenever the sort changes (a new sort re-orders the whole data set,
927
+ * so whatever page the user was on no longer means anything) and clamps down to
928
+ * `totalPages` whenever the data set or page size shrinks — but otherwise preserves
929
+ * wherever the paginator navigated to. `gog-paginator`'s own `page` model additionally
930
+ * self-clamps against `totalPages` on its own, so this only has to handle the reset case.
931
+ */
932
+ readonly currentPage: _angular_core.WritableSignal<number>;
674
933
  readonly visibleRows: _angular_core.Signal<T[]>;
675
- readonly pageNumbers: _angular_core.Signal<(number | "...")[]>;
676
934
  readonly hasPagination: _angular_core.Signal<boolean>;
677
935
  readonly emptyColspan: _angular_core.Signal<number>;
678
936
  getBodyTemplate(field: string): TemplateRef<unknown> | null;
679
937
  getHeaderTemplate(field: string): TemplateRef<unknown> | null;
680
- toggleSort(col: Column<T>): void;
938
+ toggleSort(col: Column): void;
681
939
  getSortDirection(field: string): SortDirection;
682
940
  getAriaSort(field: string): 'ascending' | 'descending' | null;
683
- goTo(page: number): void;
684
- prev(): void;
685
- next(): void;
686
- handleSortClick(col: Column<T>): void;
687
- isNumber(val: number | '...'): val is number;
941
+ handleSortClick(col: Column): void;
688
942
  getCellValue(row: T, field: string): unknown;
689
943
  formatCellValue(row: T, field: string): string;
690
944
  globalRowIndex(localIndex: number): number;
@@ -702,8 +956,14 @@ declare class SpinnerComponent {
702
956
  readonly size: _angular_core.InputSignal<GogSize>;
703
957
  readonly overlay: _angular_core.InputSignal<boolean>;
704
958
  readonly ariaLabel: _angular_core.InputSignal<string>;
959
+ /**
960
+ * `runic` and `ring` are built-in presets. Use `custom` to render your own
961
+ * markup via content projection — it inherits the size wrapper, overlay
962
+ * behaviour, and `--gog-spinner-color` theming, but the visuals are yours.
963
+ */
964
+ readonly variant: _angular_core.InputSignal<GogSpinnerVariant>;
705
965
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpinnerComponent, never>;
706
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpinnerComponent, "gog-spinner", never, { "size": { "alias": "size"; "required": false; "isSignal": true; }; "overlay": { "alias": "overlay"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
966
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpinnerComponent, "gog-spinner", never, { "size": { "alias": "size"; "required": false; "isSignal": true; }; "overlay": { "alias": "overlay"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
707
967
  }
708
968
 
709
969
  declare class ThemeService {
@@ -719,5 +979,5 @@ declare class ThemeService {
719
979
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<ThemeService>;
720
980
  }
721
981
 
722
- export { AccordionComponent, ButtonComponent, CheckboxComponent, ChipComponent, Column, ConfirmationDialogComponent, DIALOG_DATA, DIALOG_REF, DialogComponent, DialogService, GogAccordionChevronDirective, GogAccordionContentDirective, GogAccordionHeaderDirective, GogMultiselectDropdownPortal, IconComponent, InputfieldComponent, MultiselectComponent, SelectComponent, SliderComponent, SpinnerComponent, SpinnerOverlayComponent, TableComponent, TagComponent, TemplateDirective, ThemeService, ToastComponent, ToastContainerComponent, ToastService };
723
- export type { ConfirmDialogData, DialogConfig, DialogHandle, DialogRef, GogAccordionChevronContext, GogAccordionHeaderContext, GogAccordionItem, GogAccordionToggleEvent, GogDropdownDirection, GogIconName, GogMultiselectOption, GogSelectOption, GogSize, GogTableBodyContext, GogTableHeaderContext, GogTagShape, GogTagVariant, GogVariant, OpenDialog, SortDirection, Toast, ToastAction, ToastConfig, ToastPosition, ToastType };
982
+ export { AccordionComponent, ButtonComponent, CheckboxComponent, ChipComponent, Column, ConfirmationDialogComponent, DIALOG_DATA, DIALOG_REF, DialogComponent, DialogService, GogAccordionChevronDirective, GogAccordionContentDirective, GogAccordionHeaderDirective, GogDropdownBase, ICON_DEFS, IconComponent, InputfieldComponent, MultiselectComponent, PaginatorComponent, SelectComponent, SkeletonComponent, SliderComponent, SpinnerComponent, SpinnerOverlayComponent, TableComponent, TagComponent, TemplateDirective, ThemeService, ToastComponent, ToastContainerComponent, ToastService, defaultCompare };
983
+ export type { ConfirmDialogData, DialogConfig, DialogHandle, DialogRef, GogAccordionChevronContext, GogAccordionHeaderContext, GogAccordionItem, GogAccordionToggleEvent, GogDropdownDirection, GogDropdownOption, GogIconName, GogMultiselectOption, GogPaginatorRangeMode, GogSelectOption, GogSize, GogSkeletonAnimation, GogSkeletonShape, GogSpinnerVariant, GogTableBodyContext, GogTableHeaderContext, GogTagShape, GogTagVariant, GogVariant, OpenDialog, SortDirection, Toast, ToastAction, ToastConfig, ToastPosition, ToastType };