@egose/shadcn-theme-ng-tw 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +1 -1
  2. package/accordion/README.md +405 -2
  3. package/alert/README.md +372 -2
  4. package/alert-dialog/README.md +471 -5
  5. package/aspect-ratio/README.md +272 -5
  6. package/autocomplete/README.md +502 -2
  7. package/avatar/README.md +357 -5
  8. package/badge/README.md +318 -2
  9. package/basic-alert/README.md +353 -2
  10. package/breadcrumb/README.md +406 -5
  11. package/button/README.md +482 -2
  12. package/button/fesm2022/button.mjs +85 -107
  13. package/button/types/button.d.ts +5 -8
  14. package/button-group/README.md +318 -5
  15. package/button-group/fesm2022/button-group.mjs +1 -1
  16. package/calendar/README.md +357 -2
  17. package/card/README.md +331 -5
  18. package/carousel/README.md +333 -5
  19. package/carousel/fesm2022/carousel.mjs +4 -1
  20. package/checkbox/README.md +320 -2
  21. package/collapsible/README.md +332 -5
  22. package/combobox/README.md +507 -5
  23. package/combobox/fesm2022/combobox.mjs +4 -1
  24. package/command/README.md +435 -5
  25. package/confirmation-dialog/README.md +301 -2
  26. package/context-menu/README.md +366 -5
  27. package/date-picker/README.md +465 -2
  28. package/date-picker/fesm2022/date-picker.mjs +2 -2
  29. package/dialog/README.md +448 -2
  30. package/drawer/README.md +395 -5
  31. package/dropdown-menu/README.md +417 -5
  32. package/empty/README.md +329 -5
  33. package/field/README.md +385 -5
  34. package/form-checkbox/README.md +312 -2
  35. package/form-date-picker/README.md +322 -2
  36. package/form-field/README.md +356 -2
  37. package/form-field-simple/README.md +340 -2
  38. package/form-searchable-multiselect/README.md +361 -2
  39. package/form-select/README.md +350 -2
  40. package/form-text-input/README.md +371 -2
  41. package/form-textarea/README.md +347 -2
  42. package/hover-card/README.md +256 -5
  43. package/icon/README.md +239 -2
  44. package/input/README.md +269 -2
  45. package/input-group/README.md +335 -5
  46. package/input-group/fesm2022/input-group.mjs +3 -3
  47. package/input-otp/README.md +375 -5
  48. package/item/README.md +385 -5
  49. package/item/fesm2022/item.mjs +3 -3
  50. package/kbd/README.md +291 -5
  51. package/label/README.md +272 -2
  52. package/layout-simple/README.md +193 -2
  53. package/layout-simple/fesm2022/layout-simple.mjs +877 -409
  54. package/layout-simple/types/layout-simple.d.ts +174 -137
  55. package/menu/README.md +417 -2
  56. package/menubar/README.md +343 -5
  57. package/native-select/README.md +323 -5
  58. package/navigation-menu/README.md +369 -5
  59. package/package.json +1 -1
  60. package/pagination/README.md +388 -5
  61. package/popover/README.md +331 -2
  62. package/progress/README.md +311 -5
  63. package/radio-group/README.md +364 -2
  64. package/radio-group/fesm2022/radio-group.mjs +5 -1
  65. package/resizable/README.md +269 -5
  66. package/scroll-area/README.md +233 -5
  67. package/searchable-multiselect/README.md +323 -2
  68. package/select/README.md +437 -2
  69. package/separator/README.md +222 -2
  70. package/sheet/README.md +311 -2
  71. package/sidebar/README.md +457 -5
  72. package/skeleton/README.md +217 -5
  73. package/slider/README.md +273 -5
  74. package/slider/fesm2022/slider.mjs +17 -13
  75. package/sonner/README.md +346 -2
  76. package/spinner/README.md +284 -2
  77. package/switch/README.md +310 -2
  78. package/table/README.md +423 -5
  79. package/tabs/README.md +411 -2
  80. package/tabs/fesm2022/tabs.mjs +12 -2
  81. package/textarea/README.md +282 -5
  82. package/toggle/README.md +270 -5
  83. package/toggle-group/README.md +340 -5
  84. package/tooltip/README.md +269 -2
  85. package/typography/README.md +271 -5
  86. package/utils/README.md +303 -2
@@ -1,83 +1,102 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, Component, signal, computed, output, ChangeDetectionStrategy, viewChild, effect, inject, DestroyRef } from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, Component, output, signal, viewChild, viewChildren, effect, computed, inject, ElementRef, Injector, afterNextRender, DestroyRef } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule, NgTemplateOutlet } from '@angular/common';
3
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { RouterLink, RouterModule } from '@angular/router';
6
+ import { RouterLink, RouterLinkActive, Router, NavigationEnd } from '@angular/router';
7
+ import { BreakpointObserver } from '@angular/cdk/layout';
8
+ import { _IdGenerator } from '@angular/cdk/a11y';
5
9
  import { NgIcon, provideIcons } from '@ng-icons/core';
6
- import { lucideUser, lucideSearch, lucideMenu } from '@ng-icons/lucide';
10
+ import { lucideUser, lucideSearch, lucideChevronDown, lucideX, lucideMenu, lucidePanelLeft } from '@ng-icons/lucide';
7
11
  import { hlm } from '@egose/shadcn-theme-ng-tw/utils';
8
- import * as i4 from '@egose/shadcn-theme-ng-tw/button';
9
- import { HlmButton, HlmButtonImports } from '@egose/shadcn-theme-ng-tw/button';
10
- import * as i1 from '@angular/common';
11
- import { CommonModule } from '@angular/common';
12
12
  import { HlmDropdownMenu, HlmDropdownMenuTrigger, HlmDropdownMenuItem, HlmDropdownMenuLabel, HlmDropdownMenuSeparator, HlmDropdownMenuGroup } from '@egose/shadcn-theme-ng-tw/dropdown-menu';
13
- import * as i1$1 from '@angular/forms';
14
- import { FormsModule } from '@angular/forms';
13
+ import * as i3 from '@egose/shadcn-theme-ng-tw/button';
14
+ import { HlmButton, HlmButtonImports } from '@egose/shadcn-theme-ng-tw/button';
15
15
  import { HlmPopover, HlmPopoverTrigger, HlmPopoverContent, HlmPopoverPortal } from '@egose/shadcn-theme-ng-tw/popover';
16
16
  import { HlmInput } from '@egose/shadcn-theme-ng-tw/input';
17
- import * as i2 from '@spartan-ng/brain/sheet';
17
+ import * as i1$1 from '@spartan-ng/brain/sheet';
18
18
  import { BrnSheet, BrnSheetImports } from '@spartan-ng/brain/sheet';
19
- import { HlmLabelImports } from '@egose/shadcn-theme-ng-tw/label';
20
- import * as i3 from '@egose/shadcn-theme-ng-tw/sheet';
19
+ import * as i2 from '@egose/shadcn-theme-ng-tw/sheet';
21
20
  import { HlmSheetImports } from '@egose/shadcn-theme-ng-tw/sheet';
22
- import * as i1$2 from '@angular/cdk/layout';
21
+
22
+ /** Internal matching contract shared by links and dropdown destinations. */
23
+ function navigationMatchOptions(item) {
24
+ return {
25
+ paths: item.activeMatch === 'prefix' ? 'subset' : 'exact',
26
+ queryParams: 'ignored',
27
+ fragment: 'ignored',
28
+ matrixParams: 'ignored',
29
+ };
30
+ }
23
31
 
24
32
  class EgLayoutSimpleUserMenu {
25
33
  hlm = hlm;
26
- lucideUser = lucideUser;
27
- menus = input([], /* @ts-ignore */
28
- ...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
29
- menuTrigger = input(/* @ts-ignore */
30
- ...(ngDevMode ? [undefined, { debugName: "menuTrigger" }] : /* istanbul ignore next */ []));
34
+ navigationMatchOptions = navigationMatchOptions;
35
+ userIcon = lucideUser;
36
+ sections = input([], /* @ts-ignore */
37
+ ...(ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []));
38
+ triggerTemplate = input(/* @ts-ignore */
39
+ ...(ngDevMode ? [undefined, { debugName: "triggerTemplate" }] : /* istanbul ignore next */ []));
40
+ triggerLabel = input('Open account menu', /* @ts-ignore */
41
+ ...(ngDevMode ? [{ debugName: "triggerLabel" }] : /* istanbul ignore next */ []));
31
42
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleUserMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
32
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimpleUserMenu, isStandalone: true, selector: "eg-layout-simple-user-menu", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, menuTrigger: { classPropertyName: "menuTrigger", publicName: "menuTrigger", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
43
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimpleUserMenu, isStandalone: true, selector: "eg-layout-simple-user-menu", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, triggerTemplate: { classPropertyName: "triggerTemplate", publicName: "triggerTemplate", isSignal: true, isRequired: false, transformFunction: null }, triggerLabel: { classPropertyName: "triggerLabel", publicName: "triggerLabel", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
33
44
  provideIcons({
34
45
  lucideUser,
35
46
  }),
36
47
  ], ngImport: i0, template: `
37
48
  <ng-template #iconTemplate>
38
- <ng-icon [svg]="lucideUser" size="1.5rem" class="tw:[&_svg]:w-[inherit]! tw:[&_svg]:h-[inherit]!" />
49
+ <ng-icon [svg]="userIcon" size="1.25rem" aria-hidden="true" />
39
50
  </ng-template>
40
51
 
41
- @let _menuTrigger = menuTrigger();
52
+ @let customTrigger = triggerTemplate();
42
53
 
43
54
  <div class="tw:flex tw:w-full tw:items-center tw:justify-center">
44
- @if (_menuTrigger) {
55
+ @if (customTrigger) {
45
56
  <button
46
57
  type="button"
47
58
  [hlmDropdownMenuTrigger]="menu"
48
- class="tw:cursor-pointer tw:bg-transparent tw:border-0 tw:p-0"
59
+ [attr.aria-label]="triggerLabel()"
60
+ class="tw:min-h-11 tw:min-w-11 tw:rounded-full tw:cursor-pointer tw:bg-transparent tw:border-0 tw:p-0 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring"
49
61
  >
50
- <ng-container *ngTemplateOutlet="_menuTrigger" />
62
+ <ng-container *ngTemplateOutlet="customTrigger" />
51
63
  </button>
52
64
  } @else {
53
65
  <button
54
66
  hlmButton
55
- variant="primary"
67
+ type="button"
68
+ variant="secondary"
69
+ appearance="outline"
56
70
  size="icon"
57
71
  [hlmDropdownMenuTrigger]="menu"
58
72
  [icon]="iconTemplate"
59
- class="tw:rounded-full tw:border tw:border-gray-400"
73
+ [attr.aria-label]="triggerLabel()"
74
+ class="tw:size-11 tw:rounded-full tw:border tw:border-border tw:text-foreground"
60
75
  ></button>
61
76
  }
62
77
 
63
78
  <ng-template #menu>
64
79
  <div hlmDropdownMenu class="tw:w-56">
65
- @for (section of menus(); track section) {
80
+ @for (section of sections(); track $index) {
66
81
  @if (section.label) {
67
82
  <div hlmDropdownMenuLabel>{{ section.label }}</div>
68
83
  }
69
84
  @if (section.items?.length) {
70
85
  <div hlmDropdownMenuGroup>
71
86
  @for (item of section.items; track item) {
72
- @if (item.link) {
87
+ @if (item.link && !item.disabled) {
73
88
  <a
74
89
  hlmDropdownMenuItem
75
90
  [routerLink]="item.link"
76
- [class]="hlm('tw:cursor-pointer tw:no-underline', item.class)"
91
+ routerLinkActive="tw:bg-foreground/10 tw:font-semibold"
92
+ [routerLinkActiveOptions]="navigationMatchOptions(item)"
93
+ ariaCurrentWhenActive="page"
94
+ [class]="hlm('tw:min-h-11 tw:cursor-pointer tw:no-underline', item.class)"
77
95
  >
78
96
  @if (item.icon) {
79
97
  <ng-icon
80
98
  [svg]="item.icon"
99
+ aria-hidden="true"
81
100
  size="1rem"
82
101
  [class]="
83
102
  hlm(
@@ -92,12 +111,15 @@ class EgLayoutSimpleUserMenu {
92
111
  } @else {
93
112
  <button
94
113
  hlmDropdownMenuItem
114
+ type="button"
115
+ [disabled]="item.disabled || !item.action"
95
116
  (click)="item.action?.()"
96
- [class]="hlm('tw:cursor-pointer tw:no-underline', item.class)"
117
+ [class]="hlm('tw:min-h-11 tw:cursor-pointer tw:no-underline', item.class)"
97
118
  >
98
119
  @if (item.icon) {
99
120
  <ng-icon
100
121
  [svg]="item.icon"
122
+ aria-hidden="true"
101
123
  size="1rem"
102
124
  [class]="
103
125
  hlm(
@@ -120,12 +142,13 @@ class EgLayoutSimpleUserMenu {
120
142
  </div>
121
143
  </ng-template>
122
144
  </div>
123
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }, { kind: "directive", type: HlmDropdownMenuItem, selector: "[hlmDropdownMenuItem],hlm-dropdown-menu-item", inputs: ["disabled", "variant", "inset"] }, { kind: "directive", type: HlmDropdownMenuLabel, selector: "[hlmDropdownMenuLabel],hlm-dropdown-menu-label", inputs: ["inset"] }, { kind: "directive", type: HlmDropdownMenuSeparator, selector: "[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator" }, { kind: "directive", type: HlmDropdownMenuGroup, selector: "[hlmDropdownMenuGroup],hlm-dropdown-menu-group" }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }] });
145
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }, { kind: "directive", type: HlmDropdownMenuItem, selector: "[hlmDropdownMenuItem],hlm-dropdown-menu-item", inputs: ["disabled", "variant", "inset"] }, { kind: "directive", type: HlmDropdownMenuLabel, selector: "[hlmDropdownMenuLabel],hlm-dropdown-menu-label", inputs: ["inset"] }, { kind: "directive", type: HlmDropdownMenuSeparator, selector: "[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator" }, { kind: "directive", type: HlmDropdownMenuGroup, selector: "[hlmDropdownMenuGroup],hlm-dropdown-menu-group" }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
124
146
  }
125
147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleUserMenu, decorators: [{
126
148
  type: Component,
127
149
  args: [{
128
150
  selector: 'eg-layout-simple-user-menu',
151
+ changeDetection: ChangeDetectionStrategy.OnPush,
129
152
  imports: [
130
153
  CommonModule,
131
154
  HlmDropdownMenu,
@@ -137,6 +160,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
137
160
  HlmButton,
138
161
  NgIcon,
139
162
  RouterLink,
163
+ RouterLinkActive,
140
164
  ],
141
165
  providers: [
142
166
  provideIcons({
@@ -145,49 +169,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
145
169
  ],
146
170
  template: `
147
171
  <ng-template #iconTemplate>
148
- <ng-icon [svg]="lucideUser" size="1.5rem" class="tw:[&_svg]:w-[inherit]! tw:[&_svg]:h-[inherit]!" />
172
+ <ng-icon [svg]="userIcon" size="1.25rem" aria-hidden="true" />
149
173
  </ng-template>
150
174
 
151
- @let _menuTrigger = menuTrigger();
175
+ @let customTrigger = triggerTemplate();
152
176
 
153
177
  <div class="tw:flex tw:w-full tw:items-center tw:justify-center">
154
- @if (_menuTrigger) {
178
+ @if (customTrigger) {
155
179
  <button
156
180
  type="button"
157
181
  [hlmDropdownMenuTrigger]="menu"
158
- class="tw:cursor-pointer tw:bg-transparent tw:border-0 tw:p-0"
182
+ [attr.aria-label]="triggerLabel()"
183
+ class="tw:min-h-11 tw:min-w-11 tw:rounded-full tw:cursor-pointer tw:bg-transparent tw:border-0 tw:p-0 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring"
159
184
  >
160
- <ng-container *ngTemplateOutlet="_menuTrigger" />
185
+ <ng-container *ngTemplateOutlet="customTrigger" />
161
186
  </button>
162
187
  } @else {
163
188
  <button
164
189
  hlmButton
165
- variant="primary"
190
+ type="button"
191
+ variant="secondary"
192
+ appearance="outline"
166
193
  size="icon"
167
194
  [hlmDropdownMenuTrigger]="menu"
168
195
  [icon]="iconTemplate"
169
- class="tw:rounded-full tw:border tw:border-gray-400"
196
+ [attr.aria-label]="triggerLabel()"
197
+ class="tw:size-11 tw:rounded-full tw:border tw:border-border tw:text-foreground"
170
198
  ></button>
171
199
  }
172
200
 
173
201
  <ng-template #menu>
174
202
  <div hlmDropdownMenu class="tw:w-56">
175
- @for (section of menus(); track section) {
203
+ @for (section of sections(); track $index) {
176
204
  @if (section.label) {
177
205
  <div hlmDropdownMenuLabel>{{ section.label }}</div>
178
206
  }
179
207
  @if (section.items?.length) {
180
208
  <div hlmDropdownMenuGroup>
181
209
  @for (item of section.items; track item) {
182
- @if (item.link) {
210
+ @if (item.link && !item.disabled) {
183
211
  <a
184
212
  hlmDropdownMenuItem
185
213
  [routerLink]="item.link"
186
- [class]="hlm('tw:cursor-pointer tw:no-underline', item.class)"
214
+ routerLinkActive="tw:bg-foreground/10 tw:font-semibold"
215
+ [routerLinkActiveOptions]="navigationMatchOptions(item)"
216
+ ariaCurrentWhenActive="page"
217
+ [class]="hlm('tw:min-h-11 tw:cursor-pointer tw:no-underline', item.class)"
187
218
  >
188
219
  @if (item.icon) {
189
220
  <ng-icon
190
221
  [svg]="item.icon"
222
+ aria-hidden="true"
191
223
  size="1rem"
192
224
  [class]="
193
225
  hlm(
@@ -202,12 +234,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
202
234
  } @else {
203
235
  <button
204
236
  hlmDropdownMenuItem
237
+ type="button"
238
+ [disabled]="item.disabled || !item.action"
205
239
  (click)="item.action?.()"
206
- [class]="hlm('tw:cursor-pointer tw:no-underline', item.class)"
240
+ [class]="hlm('tw:min-h-11 tw:cursor-pointer tw:no-underline', item.class)"
207
241
  >
208
242
  @if (item.icon) {
209
243
  <ng-icon
210
244
  [svg]="item.icon"
245
+ aria-hidden="true"
211
246
  size="1rem"
212
247
  [class]="
213
248
  hlm(
@@ -232,146 +267,246 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
232
267
  </div>
233
268
  `,
234
269
  }]
235
- }], propDecorators: { menus: [{ type: i0.Input, args: [{ isSignal: true, alias: "menus", required: false }] }], menuTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuTrigger", required: false }] }] } });
270
+ }], propDecorators: { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], triggerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerTemplate", required: false }] }], triggerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerLabel", required: false }] }] } });
236
271
 
237
- class EgGenericAutocomplete {
238
- placeholderText = input('Select an option', /* @ts-ignore */
239
- ...(ngDevMode ? [{ debugName: "placeholderText" }] : /* istanbul ignore next */ []));
240
- emptyText = input('No options found', /* @ts-ignore */
272
+ /** Async page search with debouncing, stale-response protection, and keyboard navigation. */
273
+ class EgLayoutSearch {
274
+ placeholder = input('Search pages…', /* @ts-ignore */
275
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
276
+ emptyText = input('No matching pages found.', /* @ts-ignore */
241
277
  ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
242
- /** Loader function: takes search string, returns options. */
243
- loaderFn = input(async () => [], /* @ts-ignore */
244
- ...(ngDevMode ? [{ debugName: "loaderFn" }] : /* istanbul ignore next */ []));
245
- transformValueToSearch = input((value) => String(value), /* @ts-ignore */
246
- ...(ngDevMode ? [{ debugName: "transformValueToSearch" }] : /* istanbul ignore next */ []));
247
- search = signal('', /* @ts-ignore */
248
- ...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
249
- options = signal([], /* @ts-ignore */
250
- ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
251
- filtered = computed(() => {
252
- const opts = this.options();
253
- const search = this.search().toLowerCase();
254
- const transform = this.transformValueToSearch() ?? ((value) => String(value));
255
- const mapped = opts.map((o) => ({ label: transform(o), value: o, raw: o }));
256
- if (!search)
257
- return mapped;
258
- return mapped.filter((o) => o.label.toLowerCase().includes(search));
259
- }, /* @ts-ignore */
260
- ...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
261
- optionChange = output();
278
+ errorText = input('Search is unavailable. Please try again.', /* @ts-ignore */
279
+ ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
280
+ loadingText = input('Searching…', /* @ts-ignore */
281
+ ...(ngDevMode ? [{ debugName: "loadingText" }] : /* istanbul ignore next */ []));
282
+ retryText = input('Try again', /* @ts-ignore */
283
+ ...(ngDevMode ? [{ debugName: "retryText" }] : /* istanbul ignore next */ []));
284
+ loader = input(/* @ts-ignore */
285
+ ...(ngDevMode ? [undefined, { debugName: "loader" }] : /* istanbul ignore next */ []));
286
+ resultLabel = input(/* @ts-ignore */
287
+ ...(ngDevMode ? [undefined, { debugName: "resultLabel" }] : /* istanbul ignore next */ []));
288
+ resultTemplate = input(/* @ts-ignore */
289
+ ...(ngDevMode ? [undefined, { debugName: "resultTemplate" }] : /* istanbul ignore next */ []));
290
+ resultSelected = output();
291
+ searchIcon = lucideSearch;
292
+ query = signal('', /* @ts-ignore */
293
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
294
+ results = signal([], /* @ts-ignore */
295
+ ...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
296
+ isOpen = signal(false, /* @ts-ignore */
297
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
298
+ isLoading = signal(false, /* @ts-ignore */
299
+ ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
300
+ hasError = signal(false, /* @ts-ignore */
301
+ ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
302
+ retryVersion = signal(0, /* @ts-ignore */
303
+ ...(ngDevMode ? [{ debugName: "retryVersion" }] : /* istanbul ignore next */ []));
304
+ searchInput = viewChild('searchInput', /* @ts-ignore */
305
+ ...(ngDevMode ? [{ debugName: "searchInput" }] : /* istanbul ignore next */ []));
306
+ resultButtons = viewChildren('resultButton', /* @ts-ignore */
307
+ ...(ngDevMode ? [{ debugName: "resultButtons" }] : /* istanbul ignore next */ []));
262
308
  constructor() {
263
- // Trigger initial load
264
- this.loadOptions();
309
+ effect((onCleanup) => {
310
+ const open = this.isOpen();
311
+ const search = this.query().trim();
312
+ const loader = this.loader();
313
+ this.retryVersion();
314
+ this.results.set([]);
315
+ this.hasError.set(false);
316
+ this.isLoading.set(open && !!loader);
317
+ if (!open || !loader)
318
+ return;
319
+ // Cleanup also invalidates an in-flight request when the component is destroyed.
320
+ let cancelled = false;
321
+ const timeout = setTimeout(async () => {
322
+ try {
323
+ const results = await loader({ search });
324
+ if (!cancelled)
325
+ this.results.set(results);
326
+ }
327
+ catch {
328
+ if (!cancelled)
329
+ this.hasError.set(true);
330
+ }
331
+ finally {
332
+ if (!cancelled)
333
+ this.isLoading.set(false);
334
+ }
335
+ }, search ? 180 : 0);
336
+ onCleanup(() => {
337
+ cancelled = true;
338
+ clearTimeout(timeout);
339
+ });
340
+ });
265
341
  }
266
- async loadOptions() {
267
- const fn = this.loaderFn();
268
- if (!fn) {
269
- this.options.set([]);
270
- return;
271
- }
272
- try {
273
- const params = { search: this.search() };
274
- const result = await fn(params);
275
- this.options.set(result ?? []);
276
- }
277
- catch {
278
- this.options.set([]);
279
- }
342
+ labelFor(item) {
343
+ return this.resultLabel()?.(item) ?? String(item);
344
+ }
345
+ setOpen(open) {
346
+ this.isOpen.set(open);
347
+ if (!open)
348
+ this.query.set('');
349
+ }
350
+ retry() {
351
+ this.retryVersion.update((version) => version + 1);
280
352
  }
281
- select(opt) {
282
- this.optionChange.emit(opt.value);
283
- this.search.set('');
353
+ selectResult(item) {
354
+ this.setOpen(false);
355
+ this.resultSelected.emit(item);
284
356
  }
285
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgGenericAutocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
286
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgGenericAutocomplete, isStandalone: true, selector: "eg-generic-autocomplete", inputs: { placeholderText: { classPropertyName: "placeholderText", publicName: "placeholderText", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loaderFn: { classPropertyName: "loaderFn", publicName: "loaderFn", isSignal: true, isRequired: false, transformFunction: null }, transformValueToSearch: { classPropertyName: "transformValueToSearch", publicName: "transformValueToSearch", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, providers: [provideIcons({ lucideSearch })], ngImport: i0, template: `
287
- <hlm-popover>
357
+ focusResult(index, event) {
358
+ const buttons = this.resultButtons();
359
+ if (!buttons.length)
360
+ return;
361
+ event.preventDefault();
362
+ if (index < 0)
363
+ this.searchInput()?.nativeElement.focus();
364
+ else
365
+ buttons[Math.min(index, buttons.length - 1)]?.nativeElement.focus();
366
+ }
367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSearch, deps: [], target: i0.ɵɵFactoryTarget.Component });
368
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSearch, isStandalone: true, selector: "eg-layout-search", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, retryText: { classPropertyName: "retryText", publicName: "retryText", isSignal: true, isRequired: false, transformFunction: null }, loader: { classPropertyName: "loader", publicName: "loader", isSignal: true, isRequired: false, transformFunction: null }, resultLabel: { classPropertyName: "resultLabel", publicName: "resultLabel", isSignal: true, isRequired: false, transformFunction: null }, resultTemplate: { classPropertyName: "resultTemplate", publicName: "resultTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resultSelected: "resultSelected" }, host: { classAttribute: "tw:block tw:min-w-0" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "resultButtons", predicate: ["resultButton"], descendants: true, isSignal: true }], ngImport: i0, template: `
369
+ <hlm-popover
370
+ [state]="isOpen() ? 'open' : 'closed'"
371
+ (stateChanged)="setOpen($event === 'open')"
372
+ (closed)="setOpen(false)"
373
+ >
288
374
  <button
289
375
  hlmPopoverTrigger
290
- hlmButton
291
- variant="secondary"
292
- appearance="outline"
293
376
  type="button"
294
- class="tw:w-64 tw:justify-start tw:gap-2 tw:text-muted-foreground"
377
+ class="tw:flex tw:min-h-11 tw:w-full tw:items-center tw:gap-2 tw:rounded-lg tw:border tw:border-border tw:bg-foreground/3 tw:px-3 tw:text-left tw:text-sm tw:text-foreground/75 tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tw:md:w-56"
295
378
  >
296
- <ng-icon name="lucideSearch" size="14px" />
297
- <span class="tw:truncate">{{ placeholderText() }}</span>
379
+ <ng-icon [svg]="searchIcon" size="16px" aria-hidden="true" class="tw:shrink-0" />
380
+ <span class="tw:truncate">{{ placeholder() }}</span>
298
381
  </button>
299
-
300
- <hlm-popover-content *hlmPopoverPortal class="tw:w-64 tw:p-2">
382
+ <hlm-popover-content *hlmPopoverPortal class="tw:w-80 tw:max-w-[calc(100vw-2rem)] tw:p-2">
301
383
  <input
384
+ #searchInput
302
385
  hlmInput
303
- [ngModel]="search()"
304
- (ngModelChange)="search.set($event)"
305
- [placeholder]="placeholderText()"
306
- class="tw:mb-2"
386
+ type="search"
387
+ autocomplete="off"
388
+ [value]="query()"
389
+ (input)="query.set($any($event.target).value)"
390
+ [placeholder]="placeholder()"
391
+ [attr.aria-label]="placeholder()"
392
+ (keydown.arrowdown)="focusResult(0, $event)"
393
+ class="tw:mb-2 tw:min-h-11"
307
394
  />
308
- <div class="tw:max-h-60 tw:overflow-auto tw:flex tw:flex-col">
309
- @if (filtered().length === 0) {
310
- <span class="tw:text-xs tw:text-muted-foreground tw:px-2 tw:py-2">{{ emptyText() }}</span>
395
+ <div [attr.aria-busy]="isLoading()" class="tw:max-h-72 tw:overflow-y-auto tw:overscroll-contain">
396
+ @if (isLoading()) {
397
+ <p role="status" class="tw:px-3 tw:py-6 tw:text-center tw:text-sm tw:text-foreground/75">
398
+ {{ loadingText() }}
399
+ </p>
400
+ } @else if (hasError()) {
401
+ <div role="status" class="tw:space-y-3 tw:px-3 tw:py-4 tw:text-sm">
402
+ <p>{{ errorText() }}</p>
403
+ <button
404
+ type="button"
405
+ (click)="retry()"
406
+ class="tw:min-h-11 tw:rounded-md tw:border tw:border-border tw:px-3 tw:font-medium tw:cursor-pointer tw:focus-visible:outline-2 tw:focus-visible:outline-ring"
407
+ >
408
+ {{ retryText() }}
409
+ </button>
410
+ </div>
411
+ } @else if (!results().length) {
412
+ <p role="status" class="tw:px-3 tw:py-6 tw:text-center tw:text-sm tw:text-foreground/75">
413
+ {{ emptyText() }}
414
+ </p>
311
415
  } @else {
312
- @for (opt of filtered(); track opt.label) {
416
+ @for (result of results(); track $index; let index = $index) {
313
417
  <button
418
+ #resultButton
314
419
  type="button"
315
- (click)="select(opt)"
316
- class="tw:text-left tw:px-2 tw:py-1.5 tw:text-sm tw:rounded-sm tw:hover:bg-secondary tw:cursor-pointer"
420
+ (click)="selectResult(result)"
421
+ (keydown.arrowdown)="focusResult(index + 1, $event)"
422
+ (keydown.arrowup)="focusResult(index - 1, $event)"
423
+ (keydown.home)="focusResult(0, $event)"
424
+ (keydown.end)="focusResult(results().length - 1, $event)"
425
+ class="tw:flex tw:min-h-11 tw:w-full tw:items-center tw:rounded-md tw:px-3 tw:py-2 tw:text-left tw:text-sm tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:bg-foreground/10 tw:focus-visible:outline-2 tw:focus-visible:-outline-offset-2 tw:focus-visible:outline-ring"
317
426
  >
318
- {{ opt.label }}
427
+ @if (resultTemplate(); as template) {
428
+ <ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: result }" />
429
+ } @else {
430
+ {{ labelFor(result) }}
431
+ }
319
432
  </button>
320
433
  }
321
434
  }
322
435
  </div>
323
436
  </hlm-popover-content>
324
437
  </hlm-popover>
325
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: HlmPopoverTrigger, selector: "button[hlmPopoverTrigger],button[hlmPopoverTriggerFor]" }, { kind: "directive", type: HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
438
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: HlmPopoverTrigger, selector: "button[hlmPopoverTrigger],button[hlmPopoverTriggerFor]" }, { kind: "directive", type: HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
326
439
  }
327
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgGenericAutocomplete, decorators: [{
440
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSearch, decorators: [{
328
441
  type: Component,
329
442
  args: [{
330
- selector: 'eg-generic-autocomplete',
331
- imports: [
332
- FormsModule,
333
- HlmPopover,
334
- HlmPopoverTrigger,
335
- HlmPopoverContent,
336
- HlmPopoverPortal,
337
- HlmInput,
338
- HlmButton,
339
- NgIcon,
340
- ],
341
- providers: [provideIcons({ lucideSearch })],
443
+ selector: 'eg-layout-search',
444
+ imports: [NgTemplateOutlet, HlmPopover, HlmPopoverTrigger, HlmPopoverContent, HlmPopoverPortal, HlmInput, NgIcon],
445
+ host: { class: 'tw:block tw:min-w-0' },
342
446
  template: `
343
- <hlm-popover>
447
+ <hlm-popover
448
+ [state]="isOpen() ? 'open' : 'closed'"
449
+ (stateChanged)="setOpen($event === 'open')"
450
+ (closed)="setOpen(false)"
451
+ >
344
452
  <button
345
453
  hlmPopoverTrigger
346
- hlmButton
347
- variant="secondary"
348
- appearance="outline"
349
454
  type="button"
350
- class="tw:w-64 tw:justify-start tw:gap-2 tw:text-muted-foreground"
455
+ class="tw:flex tw:min-h-11 tw:w-full tw:items-center tw:gap-2 tw:rounded-lg tw:border tw:border-border tw:bg-foreground/3 tw:px-3 tw:text-left tw:text-sm tw:text-foreground/75 tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tw:md:w-56"
351
456
  >
352
- <ng-icon name="lucideSearch" size="14px" />
353
- <span class="tw:truncate">{{ placeholderText() }}</span>
457
+ <ng-icon [svg]="searchIcon" size="16px" aria-hidden="true" class="tw:shrink-0" />
458
+ <span class="tw:truncate">{{ placeholder() }}</span>
354
459
  </button>
355
-
356
- <hlm-popover-content *hlmPopoverPortal class="tw:w-64 tw:p-2">
460
+ <hlm-popover-content *hlmPopoverPortal class="tw:w-80 tw:max-w-[calc(100vw-2rem)] tw:p-2">
357
461
  <input
462
+ #searchInput
358
463
  hlmInput
359
- [ngModel]="search()"
360
- (ngModelChange)="search.set($event)"
361
- [placeholder]="placeholderText()"
362
- class="tw:mb-2"
464
+ type="search"
465
+ autocomplete="off"
466
+ [value]="query()"
467
+ (input)="query.set($any($event.target).value)"
468
+ [placeholder]="placeholder()"
469
+ [attr.aria-label]="placeholder()"
470
+ (keydown.arrowdown)="focusResult(0, $event)"
471
+ class="tw:mb-2 tw:min-h-11"
363
472
  />
364
- <div class="tw:max-h-60 tw:overflow-auto tw:flex tw:flex-col">
365
- @if (filtered().length === 0) {
366
- <span class="tw:text-xs tw:text-muted-foreground tw:px-2 tw:py-2">{{ emptyText() }}</span>
473
+ <div [attr.aria-busy]="isLoading()" class="tw:max-h-72 tw:overflow-y-auto tw:overscroll-contain">
474
+ @if (isLoading()) {
475
+ <p role="status" class="tw:px-3 tw:py-6 tw:text-center tw:text-sm tw:text-foreground/75">
476
+ {{ loadingText() }}
477
+ </p>
478
+ } @else if (hasError()) {
479
+ <div role="status" class="tw:space-y-3 tw:px-3 tw:py-4 tw:text-sm">
480
+ <p>{{ errorText() }}</p>
481
+ <button
482
+ type="button"
483
+ (click)="retry()"
484
+ class="tw:min-h-11 tw:rounded-md tw:border tw:border-border tw:px-3 tw:font-medium tw:cursor-pointer tw:focus-visible:outline-2 tw:focus-visible:outline-ring"
485
+ >
486
+ {{ retryText() }}
487
+ </button>
488
+ </div>
489
+ } @else if (!results().length) {
490
+ <p role="status" class="tw:px-3 tw:py-6 tw:text-center tw:text-sm tw:text-foreground/75">
491
+ {{ emptyText() }}
492
+ </p>
367
493
  } @else {
368
- @for (opt of filtered(); track opt.label) {
494
+ @for (result of results(); track $index; let index = $index) {
369
495
  <button
496
+ #resultButton
370
497
  type="button"
371
- (click)="select(opt)"
372
- class="tw:text-left tw:px-2 tw:py-1.5 tw:text-sm tw:rounded-sm tw:hover:bg-secondary tw:cursor-pointer"
498
+ (click)="selectResult(result)"
499
+ (keydown.arrowdown)="focusResult(index + 1, $event)"
500
+ (keydown.arrowup)="focusResult(index - 1, $event)"
501
+ (keydown.home)="focusResult(0, $event)"
502
+ (keydown.end)="focusResult(results().length - 1, $event)"
503
+ class="tw:flex tw:min-h-11 tw:w-full tw:items-center tw:rounded-md tw:px-3 tw:py-2 tw:text-left tw:text-sm tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:bg-foreground/10 tw:focus-visible:outline-2 tw:focus-visible:-outline-offset-2 tw:focus-visible:outline-ring"
373
504
  >
374
- {{ opt.label }}
505
+ @if (resultTemplate(); as template) {
506
+ <ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: result }" />
507
+ } @else {
508
+ {{ labelFor(result) }}
509
+ }
375
510
  </button>
376
511
  }
377
512
  }
@@ -381,337 +516,666 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
381
516
  `,
382
517
  changeDetection: ChangeDetectionStrategy.OnPush,
383
518
  }]
384
- }], ctorParameters: () => [], propDecorators: { placeholderText: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderText", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loaderFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "loaderFn", required: false }] }], transformValueToSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformValueToSearch", required: false }] }], optionChange: [{ type: i0.Output, args: ["optionChange"] }] } });
519
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], retryText: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryText", required: false }] }], loader: [{ type: i0.Input, args: [{ isSignal: true, alias: "loader", required: false }] }], resultLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabel", required: false }] }], resultTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultTemplate", required: false }] }], resultSelected: [{ type: i0.Output, args: ["resultSelected"] }], searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], resultButtons: [{ type: i0.ViewChildren, args: ['resultButton', { isSignal: true }] }] } });
385
520
 
386
521
  class EgLayoutSimpleSidebar {
387
- viewchildSheetRef = viewChild(BrnSheet, /* @ts-ignore */
388
- ...(ngDevMode ? [{ debugName: "viewchildSheetRef" }] : /* istanbul ignore next */ []));
389
- side = input('left', /* @ts-ignore */
390
- ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
391
- title = input('', /* @ts-ignore */
522
+ sheet = viewChild(BrnSheet, /* @ts-ignore */
523
+ ...(ngDevMode ? [{ debugName: "sheet" }] : /* istanbul ignore next */ []));
524
+ panelId = input.required(/* @ts-ignore */
525
+ ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
526
+ title = input('Navigation', /* @ts-ignore */
392
527
  ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
393
528
  content = input(/* @ts-ignore */
394
529
  ...(ngDevMode ? [undefined, { debugName: "content" }] : /* istanbul ignore next */ []));
395
530
  contentContext = input(null, /* @ts-ignore */
396
531
  ...(ngDevMode ? [{ debugName: "contentContext" }] : /* istanbul ignore next */ []));
397
- constructor() {
398
- effect(() => { });
532
+ open() {
533
+ this.sheet()?.open();
399
534
  }
400
- openSheet() {
401
- this.viewchildSheetRef()?.open();
402
- }
403
- closeSheet() {
404
- this.viewchildSheetRef()?.close();
535
+ close() {
536
+ this.sheet()?.close();
405
537
  }
406
538
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
407
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimpleSidebar, isStandalone: true, selector: "eg-layout-simple-sidebar", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, contentContext: { classPropertyName: "contentContext", publicName: "contentContext", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "viewchildSheetRef", first: true, predicate: BrnSheet, descendants: true, isSignal: true }], ngImport: i0, template: `
408
- @let _title = title();
409
- @let _content = content();
410
-
411
- <hlm-sheet id="eg-layout-simple-sidebar" [side]="side() ?? 'left'">
412
- <hlm-sheet-content *brnSheetContent="let ctx" class="tw:gap-0">
413
- @if (_title) {
414
- <hlm-sheet-header>
415
- <h3 hlmSheetTitle>{{ _title }}</h3>
416
- </hlm-sheet-header>
417
- }
418
-
419
- @if (_content) {
420
- <ng-container *ngTemplateOutlet="_content; context: contentContext()"></ng-container>
421
- }
422
-
423
- <hlm-sheet-footer>
424
- <button brnSheetClose hlmButton variant="secondary" appearance="outline-filled">Close</button>
539
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: EgLayoutSimpleSidebar, isStandalone: true, selector: "eg-layout-simple-sidebar", inputs: { panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, contentContext: { classPropertyName: "contentContext", publicName: "contentContext", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sheet", first: true, predicate: BrnSheet, descendants: true, isSignal: true }], ngImport: i0, template: `
540
+ <hlm-sheet [id]="panelId()" side="left">
541
+ <hlm-sheet-content
542
+ *brnSheetContent="let context"
543
+ class="tw:flex tw:h-full tw:max-w-[calc(100vw-2rem)] tw:flex-col tw:gap-0"
544
+ >
545
+ <hlm-sheet-header class="tw:shrink-0 tw:border-b tw:border-border tw:pr-12">
546
+ <h2 hlmSheetTitle>{{ title() }}</h2>
547
+ </hlm-sheet-header>
548
+ <div class="tw:min-h-0 tw:flex-1 tw:overflow-y-auto tw:overscroll-contain tw:p-4">
549
+ <ng-container [ngTemplateOutlet]="content() ?? null" [ngTemplateOutletContext]="contentContext()" />
550
+ </div>
551
+ <hlm-sheet-footer class="tw:shrink-0 tw:border-t tw:border-border">
552
+ <button type="button" brnSheetClose hlmButton variant="secondary" appearance="outline">
553
+ Close navigation
554
+ </button>
425
555
  </hlm-sheet-footer>
426
556
  </hlm-sheet-content>
427
557
  </hlm-sheet>
428
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.BrnSheetClose, selector: "button[brnSheetClose]" }, { kind: "directive", type: i2.BrnSheetContent, selector: "[brnSheetContent]" }, { kind: "component", type: i3.HlmSheet, selector: "hlm-sheet", exportAs: ["hlmSheet"] }, { kind: "component", type: i3.HlmSheetContent, selector: "hlm-sheet-content", inputs: ["class"] }, { kind: "component", type: i3.HlmSheetFooter, selector: "hlm-sheet-footer", inputs: ["class"] }, { kind: "component", type: i3.HlmSheetHeader, selector: "hlm-sheet-header", inputs: ["class"] }, { kind: "directive", type: i3.HlmSheetTitle, selector: "[hlmSheetTitle]", inputs: ["class"] }, { kind: "component", type: i4.HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }] });
558
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.BrnSheetClose, selector: "button[brnSheetClose]" }, { kind: "directive", type: i1$1.BrnSheetContent, selector: "[brnSheetContent]" }, { kind: "component", type: i2.HlmSheet, selector: "hlm-sheet", exportAs: ["hlmSheet"] }, { kind: "component", type: i2.HlmSheetContent, selector: "hlm-sheet-content", inputs: ["class"] }, { kind: "component", type: i2.HlmSheetFooter, selector: "hlm-sheet-footer", inputs: ["class"] }, { kind: "component", type: i2.HlmSheetHeader, selector: "hlm-sheet-header", inputs: ["class"] }, { kind: "directive", type: i2.HlmSheetTitle, selector: "[hlmSheetTitle]", inputs: ["class"] }, { kind: "component", type: i3.HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
429
559
  }
430
560
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleSidebar, decorators: [{
431
561
  type: Component,
432
562
  args: [{
433
563
  selector: 'eg-layout-simple-sidebar',
434
- standalone: true,
435
- imports: [CommonModule, RouterModule, BrnSheetImports, HlmSheetImports, HlmButtonImports, HlmLabelImports],
564
+ imports: [NgTemplateOutlet, BrnSheetImports, HlmSheetImports, HlmButtonImports],
565
+ changeDetection: ChangeDetectionStrategy.OnPush,
436
566
  template: `
437
- @let _title = title();
438
- @let _content = content();
439
-
440
- <hlm-sheet id="eg-layout-simple-sidebar" [side]="side() ?? 'left'">
441
- <hlm-sheet-content *brnSheetContent="let ctx" class="tw:gap-0">
442
- @if (_title) {
443
- <hlm-sheet-header>
444
- <h3 hlmSheetTitle>{{ _title }}</h3>
445
- </hlm-sheet-header>
446
- }
447
-
448
- @if (_content) {
449
- <ng-container *ngTemplateOutlet="_content; context: contentContext()"></ng-container>
450
- }
451
-
452
- <hlm-sheet-footer>
453
- <button brnSheetClose hlmButton variant="secondary" appearance="outline-filled">Close</button>
567
+ <hlm-sheet [id]="panelId()" side="left">
568
+ <hlm-sheet-content
569
+ *brnSheetContent="let context"
570
+ class="tw:flex tw:h-full tw:max-w-[calc(100vw-2rem)] tw:flex-col tw:gap-0"
571
+ >
572
+ <hlm-sheet-header class="tw:shrink-0 tw:border-b tw:border-border tw:pr-12">
573
+ <h2 hlmSheetTitle>{{ title() }}</h2>
574
+ </hlm-sheet-header>
575
+ <div class="tw:min-h-0 tw:flex-1 tw:overflow-y-auto tw:overscroll-contain tw:p-4">
576
+ <ng-container [ngTemplateOutlet]="content() ?? null" [ngTemplateOutletContext]="contentContext()" />
577
+ </div>
578
+ <hlm-sheet-footer class="tw:shrink-0 tw:border-t tw:border-border">
579
+ <button type="button" brnSheetClose hlmButton variant="secondary" appearance="outline">
580
+ Close navigation
581
+ </button>
454
582
  </hlm-sheet-footer>
455
583
  </hlm-sheet-content>
456
584
  </hlm-sheet>
457
585
  `,
458
586
  }]
459
- }], ctorParameters: () => [], propDecorators: { viewchildSheetRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnSheet), { isSignal: true }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], contentContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentContext", required: false }] }] } });
587
+ }], propDecorators: { sheet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnSheet), { isSignal: true }] }], panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], contentContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentContext", required: false }] }] } });
588
+
589
+ /** Internal shared renderer keeps desktop, mobile, and footer navigation consistent. */
590
+ class EgLayoutNavigationItem {
591
+ item = input.required(/* @ts-ignore */
592
+ ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
593
+ itemClass = input('', /* @ts-ignore */
594
+ ...(ngDevMode ? [{ debugName: "itemClass" }] : /* istanbul ignore next */ []));
595
+ appearance = input('link', /* @ts-ignore */
596
+ ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
597
+ selected = output();
598
+ activeClasses = 'tw:bg-foreground/10 tw:font-semibold tw:underline tw:decoration-2 tw:underline-offset-4';
599
+ classes = computed(() => hlm('tw:flex tw:min-h-11 tw:w-full tw:items-center tw:gap-2 tw:rounded-lg tw:px-3 tw:py-2 tw:text-left tw:text-sm tw:font-medium tw:text-foreground tw:no-underline tw:cursor-pointer tw:motion-safe:transition-colors tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tw:disabled:cursor-not-allowed tw:disabled:opacity-50', this.appearance() === 'card' &&
600
+ 'tw:h-full tw:min-h-11 tw:md:min-h-24 tw:flex-col tw:items-start tw:justify-between tw:gap-5 tw:rounded-xl tw:border tw:border-transparent tw:bg-foreground/3 tw:p-4 tw:font-semibold tw:break-words tw:hover:border-border tw:hover:bg-foreground/7', this.itemClass(), this.item().class), /* @ts-ignore */
601
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
602
+ matchOptions = computed(() => navigationMatchOptions(this.item()), /* @ts-ignore */
603
+ ...(ngDevMode ? [{ debugName: "matchOptions" }] : /* istanbul ignore next */ []));
604
+ activate() {
605
+ const item = this.item();
606
+ if (item.disabled || !item.action)
607
+ return;
608
+ item.action();
609
+ this.selected.emit(item);
610
+ }
611
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutNavigationItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
612
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutNavigationItem, isStandalone: true, selector: "eg-layout-navigation-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, host: { classAttribute: "tw:block tw:min-w-0 tw:shrink-0" }, ngImport: i0, template: `
613
+ @let entry = item();
614
+ @if (entry.link && !entry.disabled) {
615
+ <a
616
+ [routerLink]="entry.link"
617
+ [routerLinkActive]="activeClasses"
618
+ [routerLinkActiveOptions]="matchOptions()"
619
+ ariaCurrentWhenActive="page"
620
+ [class]="classes()"
621
+ (click)="selected.emit(entry)"
622
+ >
623
+ <ng-container [ngTemplateOutlet]="content" />
624
+ </a>
625
+ } @else {
626
+ <button type="button" [class]="classes()" [disabled]="entry.disabled || !entry.action" (click)="activate()">
627
+ <ng-container [ngTemplateOutlet]="content" />
628
+ </button>
629
+ }
630
+ <ng-template #content>
631
+ @if (entry.icon) {
632
+ <ng-icon
633
+ [svg]="entry.icon"
634
+ [size]="appearance() === 'card' ? '1.25rem' : '1rem'"
635
+ aria-hidden="true"
636
+ class="tw:shrink-0"
637
+ />
638
+ }
639
+ <span class="tw:min-w-0">
640
+ <span class="tw:block">{{ entry.label }}</span>
641
+ @if (appearance() === 'card' && entry.description) {
642
+ <span class="tw:mt-1.5 tw:block tw:text-sm tw:font-normal tw:leading-relaxed tw:text-foreground/75">{{
643
+ entry.description
644
+ }}</span>
645
+ }
646
+ </span>
647
+ </ng-template>
648
+ `, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
649
+ }
650
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutNavigationItem, decorators: [{
651
+ type: Component,
652
+ args: [{
653
+ selector: 'eg-layout-navigation-item',
654
+ imports: [RouterLink, RouterLinkActive, NgIcon, NgTemplateOutlet],
655
+ changeDetection: ChangeDetectionStrategy.OnPush,
656
+ host: { class: 'tw:block tw:min-w-0 tw:shrink-0' },
657
+ template: `
658
+ @let entry = item();
659
+ @if (entry.link && !entry.disabled) {
660
+ <a
661
+ [routerLink]="entry.link"
662
+ [routerLinkActive]="activeClasses"
663
+ [routerLinkActiveOptions]="matchOptions()"
664
+ ariaCurrentWhenActive="page"
665
+ [class]="classes()"
666
+ (click)="selected.emit(entry)"
667
+ >
668
+ <ng-container [ngTemplateOutlet]="content" />
669
+ </a>
670
+ } @else {
671
+ <button type="button" [class]="classes()" [disabled]="entry.disabled || !entry.action" (click)="activate()">
672
+ <ng-container [ngTemplateOutlet]="content" />
673
+ </button>
674
+ }
675
+ <ng-template #content>
676
+ @if (entry.icon) {
677
+ <ng-icon
678
+ [svg]="entry.icon"
679
+ [size]="appearance() === 'card' ? '1.25rem' : '1rem'"
680
+ aria-hidden="true"
681
+ class="tw:shrink-0"
682
+ />
683
+ }
684
+ <span class="tw:min-w-0">
685
+ <span class="tw:block">{{ entry.label }}</span>
686
+ @if (appearance() === 'card' && entry.description) {
687
+ <span class="tw:mt-1.5 tw:block tw:text-sm tw:font-normal tw:leading-relaxed tw:text-foreground/75">{{
688
+ entry.description
689
+ }}</span>
690
+ }
691
+ </span>
692
+ </ng-template>
693
+ `,
694
+ }]
695
+ }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }] } });
460
696
 
461
697
  class EgLayoutSimpleMobileMenuGroup {
462
- hlm = hlm;
463
- label = input('', /* @ts-ignore */
464
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
698
+ label = input(/* @ts-ignore */
699
+ ...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
465
700
  items = input(/* @ts-ignore */
466
701
  ...(ngDevMode ? [undefined, { debugName: "items" }] : /* istanbul ignore next */ []));
467
- itemClick = output();
468
- handleClick(item) {
469
- item.action?.();
470
- this.itemClick.emit(item);
471
- }
702
+ itemSelected = output();
472
703
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleMobileMenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
473
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimpleMobileMenuGroup, isStandalone: true, selector: "eg-layout-simple-mobile-menu-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, providers: [], ngImport: i0, template: `
474
- @let _label = label();
475
- @let _items = items();
476
-
477
- @if (_items && _items.length > 0) {
478
- @if (_label) {
479
- <div class="tw:px-3 tw:py-1 tw:text-xs tw:font-semibold tw:text-muted-foreground">{{ _label }}</div>
704
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimpleMobileMenuGroup, isStandalone: true, selector: "eg-layout-simple-mobile-menu-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, host: { classAttribute: "tw:block tw:empty:hidden" }, ngImport: i0, template: `
705
+ @if (items()?.length) {
706
+ @if (label()) {
707
+ <div class="tw:px-3 tw:pb-2 tw:text-xs tw:font-semibold tw:text-foreground/75">{{ label() }}</div>
480
708
  }
481
- <div class="tw:flex tw:flex-col">
482
- @for (item of _items; track item.label) {
483
- @if (item.link) {
484
- <a
485
- [routerLink]="item.link"
486
- [class]="
487
- hlm(
488
- 'tw:cursor-pointer tw:no-underline tw:px-3 tw:py-2 tw:text-sm tw:hover:bg-secondary tw:rounded-sm tw:flex tw:items-center tw:gap-2'
489
- )
490
- "
491
- (click)="handleClick(item)"
492
- >
493
- @if (item.icon) {
494
- <ng-icon [svg]="item.icon" size="1rem" [class]="hlm('tw:cursor-pointer tw:mr-2')"> </ng-icon>
495
- }
496
- <span>{{ item.label }}</span>
497
- </a>
498
- } @else {
499
- <button
500
- type="button"
501
- (click)="handleClick(item)"
502
- [class]="
503
- hlm(
504
- 'tw:cursor-pointer tw:no-underline tw:px-3 tw:py-2 tw:text-sm tw:hover:bg-secondary tw:rounded-sm tw:flex tw:items-center tw:gap-2 tw:bg-transparent tw:border-0 tw:text-left tw:w-full'
505
- )
506
- "
507
- >
508
- @if (item.icon) {
509
- <ng-icon [svg]="item.icon" size="1rem" [class]="hlm('tw:cursor-pointer tw:mr-2')"> </ng-icon>
510
- }
511
- <span>{{ item.label }}</span>
512
- </button>
513
- }
709
+ <div class="tw:grid tw:gap-1">
710
+ @for (item of items(); track $index) {
711
+ <eg-layout-navigation-item [item]="item" (selected)="itemSelected.emit($event)" />
514
712
  }
515
713
  </div>
516
714
  }
517
- `, isInline: true, dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }] });
715
+ `, isInline: true, dependencies: [{ kind: "component", type: EgLayoutNavigationItem, selector: "eg-layout-navigation-item", inputs: ["item", "itemClass", "appearance"], outputs: ["selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
518
716
  }
519
717
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimpleMobileMenuGroup, decorators: [{
520
718
  type: Component,
521
719
  args: [{
522
720
  selector: 'eg-layout-simple-mobile-menu-group',
523
- imports: [NgIcon, RouterLink],
524
- providers: [],
721
+ imports: [EgLayoutNavigationItem],
722
+ changeDetection: ChangeDetectionStrategy.OnPush,
723
+ host: { class: 'tw:block tw:empty:hidden' },
525
724
  template: `
526
- @let _label = label();
527
- @let _items = items();
528
-
529
- @if (_items && _items.length > 0) {
530
- @if (_label) {
531
- <div class="tw:px-3 tw:py-1 tw:text-xs tw:font-semibold tw:text-muted-foreground">{{ _label }}</div>
725
+ @if (items()?.length) {
726
+ @if (label()) {
727
+ <div class="tw:px-3 tw:pb-2 tw:text-xs tw:font-semibold tw:text-foreground/75">{{ label() }}</div>
532
728
  }
533
- <div class="tw:flex tw:flex-col">
534
- @for (item of _items; track item.label) {
535
- @if (item.link) {
536
- <a
537
- [routerLink]="item.link"
538
- [class]="
539
- hlm(
540
- 'tw:cursor-pointer tw:no-underline tw:px-3 tw:py-2 tw:text-sm tw:hover:bg-secondary tw:rounded-sm tw:flex tw:items-center tw:gap-2'
541
- )
542
- "
543
- (click)="handleClick(item)"
544
- >
545
- @if (item.icon) {
546
- <ng-icon [svg]="item.icon" size="1rem" [class]="hlm('tw:cursor-pointer tw:mr-2')"> </ng-icon>
547
- }
548
- <span>{{ item.label }}</span>
549
- </a>
550
- } @else {
551
- <button
552
- type="button"
553
- (click)="handleClick(item)"
554
- [class]="
555
- hlm(
556
- 'tw:cursor-pointer tw:no-underline tw:px-3 tw:py-2 tw:text-sm tw:hover:bg-secondary tw:rounded-sm tw:flex tw:items-center tw:gap-2 tw:bg-transparent tw:border-0 tw:text-left tw:w-full'
557
- )
558
- "
559
- >
560
- @if (item.icon) {
561
- <ng-icon [svg]="item.icon" size="1rem" [class]="hlm('tw:cursor-pointer tw:mr-2')"> </ng-icon>
562
- }
563
- <span>{{ item.label }}</span>
564
- </button>
565
- }
729
+ <div class="tw:grid tw:gap-1">
730
+ @for (item of items(); track $index) {
731
+ <eg-layout-navigation-item [item]="item" (selected)="itemSelected.emit($event)" />
566
732
  }
567
733
  </div>
568
734
  }
569
735
  `,
570
736
  }]
571
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
737
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }] } });
572
738
 
573
- /**
574
- * Single viewport contract for the shell: below Tailwind's `md` (768px) breakpoint the
575
- * mobile menu trigger replaces all desktop navigation rows. CSS (`tw:hidden tw:md:flex`)
576
- * and runtime rendering both derive from this one boundary.
577
- */
739
+ /** Internal disclosure navigation: native links, normal Tab order, no application-menu roles. */
740
+ class EgLayoutFlyoutNavbar {
741
+ groups = input.required(/* @ts-ignore */
742
+ ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
743
+ label = input('Fly-out navigation', /* @ts-ignore */
744
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
745
+ closeLabel = input('Close navigation panel', /* @ts-ignore */
746
+ ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
747
+ navbarClass = input('', /* @ts-ignore */
748
+ ...(ngDevMode ? [{ debugName: "navbarClass" }] : /* istanbul ignore next */ []));
749
+ panelClass = input('', /* @ts-ignore */
750
+ ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
751
+ itemClass = input('', /* @ts-ignore */
752
+ ...(ngDevMode ? [{ debugName: "itemClass" }] : /* istanbul ignore next */ []));
753
+ host = inject(ElementRef);
754
+ injector = inject(Injector);
755
+ router = inject(Router);
756
+ currentUrl = signal(this.router.url, /* @ts-ignore */
757
+ ...(ngDevMode ? [{ debugName: "currentUrl" }] : /* istanbul ignore next */ []));
758
+ triggers = viewChildren('trigger', /* @ts-ignore */
759
+ ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
760
+ panel = viewChild('panel', /* @ts-ignore */
761
+ ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
762
+ id = inject(_IdGenerator).getId('eg-layout-flyout-');
763
+ hlm = hlm;
764
+ chevronIcon = lucideChevronDown;
765
+ closeIcon = lucideX;
766
+ openIndex = signal(null, /* @ts-ignore */
767
+ ...(ngDevMode ? [{ debugName: "openIndex" }] : /* istanbul ignore next */ []));
768
+ navbarClasses = computed(() => hlm('tw:flex tw:flex-wrap tw:items-center tw:gap-1 tw:border-b tw:border-border tw:bg-background tw:px-4 tw:py-2 tw:sm:px-6', this.navbarClass()), /* @ts-ignore */
769
+ ...(ngDevMode ? [{ debugName: "navbarClasses" }] : /* istanbul ignore next */ []));
770
+ panelClasses = computed(() => hlm('tw:absolute tw:inset-x-0 tw:top-full tw:max-h-[min(70dvh,36rem)] tw:overflow-y-auto tw:overscroll-contain tw:rounded-b-2xl tw:border tw:border-t-0 tw:border-border tw:bg-background tw:p-5 tw:text-foreground tw:shadow-xl tw:sm:p-6', this.panelClass()), /* @ts-ignore */
771
+ ...(ngDevMode ? [{ debugName: "panelClasses" }] : /* istanbul ignore next */ []));
772
+ activeGroups = computed(() => {
773
+ this.currentUrl();
774
+ return this.groups().map((group) => group.items.some((item) => item.link && !item.disabled && this.router.isActive(item.link, navigationMatchOptions(item))));
775
+ }, /* @ts-ignore */
776
+ ...(ngDevMode ? [{ debugName: "activeGroups" }] : /* istanbul ignore next */ []));
777
+ constructor() {
778
+ this.router.events.pipe(takeUntilDestroyed()).subscribe((event) => {
779
+ if (event instanceof NavigationEnd) {
780
+ this.currentUrl.set(event.urlAfterRedirects);
781
+ this.close();
782
+ }
783
+ });
784
+ effect(() => {
785
+ this.groups();
786
+ this.close();
787
+ });
788
+ }
789
+ toggle(index) {
790
+ this.openIndex.update((open) => (open === index ? null : index));
791
+ }
792
+ close(restoreFocus = false) {
793
+ const index = restoreFocus ? this.openIndex() : null;
794
+ this.openIndex.set(null);
795
+ if (restoreFocus && index !== null)
796
+ this.triggers()[index]?.nativeElement.focus();
797
+ }
798
+ closeOnOutsidePointer(event) {
799
+ if (!this.host.nativeElement.contains(event.target))
800
+ this.close();
801
+ }
802
+ closeOnFocusOut(event) {
803
+ if (!this.host.nativeElement.contains(event.relatedTarget))
804
+ this.close();
805
+ }
806
+ onEscape(event) {
807
+ if (this.openIndex() === null)
808
+ return;
809
+ event.preventDefault();
810
+ event.stopPropagation();
811
+ this.close(true);
812
+ }
813
+ onTriggerKeydown(event, index) {
814
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
815
+ event.preventDefault();
816
+ this.openIndex.set(index);
817
+ afterNextRender(() => {
818
+ const items = this.panel()?.nativeElement.querySelectorAll('eg-layout-navigation-item a, eg-layout-navigation-item button:not(:disabled)');
819
+ const position = event.key === 'ArrowUp' ? (items?.length ?? 0) - 1 : 0;
820
+ items?.[position]?.focus();
821
+ }, { injector: this.injector });
822
+ return;
823
+ }
824
+ const triggers = this.triggers()
825
+ .map((trigger) => trigger.nativeElement)
826
+ .filter((trigger) => !trigger.disabled);
827
+ const current = triggers.indexOf(event.currentTarget);
828
+ let next;
829
+ switch (event.key) {
830
+ case 'ArrowRight':
831
+ next = (current + 1) % triggers.length;
832
+ break;
833
+ case 'ArrowLeft':
834
+ next = (current - 1 + triggers.length) % triggers.length;
835
+ break;
836
+ case 'Home':
837
+ next = 0;
838
+ break;
839
+ case 'End':
840
+ next = triggers.length - 1;
841
+ break;
842
+ default:
843
+ return;
844
+ }
845
+ event.preventDefault();
846
+ this.close();
847
+ triggers[next]?.focus();
848
+ }
849
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutFlyoutNavbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
850
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutFlyoutNavbar, isStandalone: true, selector: "eg-layout-flyout-navbar", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, navbarClass: { classPropertyName: "navbarClass", publicName: "navbarClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:pointerdown": "closeOnOutsidePointer($event)", "focusout": "closeOnFocusOut($event)", "keydown.escape": "onEscape($event)" }, classAttribute: "tw:relative tw:z-20 tw:block tw:min-w-0" }, viewQueries: [{ propertyName: "triggers", predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
851
+ <nav [attr.aria-label]="label()" [class]="navbarClasses()">
852
+ @for (group of groups(); track $index; let index = $index) {
853
+ <button
854
+ #trigger
855
+ type="button"
856
+ [id]="id + '-trigger-' + index"
857
+ [attr.aria-controls]="id + '-panel-' + index"
858
+ [attr.aria-expanded]="openIndex() === index"
859
+ [disabled]="!group.items.length"
860
+ (click)="toggle(index)"
861
+ (keydown)="onTriggerKeydown($event, index)"
862
+ [attr.data-active]="activeGroups()[index] ? '' : null"
863
+ [class]="
864
+ hlm(
865
+ 'tw:flex tw:min-h-11 tw:items-center tw:gap-2 tw:rounded-lg tw:px-3 tw:py-2 tw:text-left tw:text-sm tw:font-medium tw:text-foreground tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tw:disabled:cursor-not-allowed tw:disabled:opacity-50',
866
+ (openIndex() === index || activeGroups()[index]) && 'tw:bg-foreground/7 tw:font-semibold'
867
+ )
868
+ "
869
+ >
870
+ @if (group.icon) {
871
+ <ng-icon [svg]="group.icon" size="1rem" aria-hidden="true" />
872
+ }
873
+ {{ group.label }}
874
+ <ng-icon
875
+ [svg]="chevronIcon"
876
+ size="14px"
877
+ aria-hidden="true"
878
+ [class]="hlm('tw:shrink-0 tw:motion-safe:transition-transform', openIndex() === index && 'tw:rotate-180')"
879
+ />
880
+ </button>
881
+ @if (openIndex() === index) {
882
+ <section
883
+ #panel
884
+ [id]="id + '-panel-' + index"
885
+ [attr.aria-labelledby]="id + '-trigger-' + index"
886
+ data-slot="flyout-panel"
887
+ [class]="panelClasses()"
888
+ >
889
+ <div class="tw:mb-4 tw:flex tw:items-start tw:justify-between tw:gap-4">
890
+ <div class="tw:space-y-1">
891
+ <p class="tw:text-xs tw:font-semibold tw:uppercase tw:tracking-wider tw:text-foreground/75">
892
+ {{ group.label }}
893
+ </p>
894
+ @if (group.description) {
895
+ <p class="tw:max-w-2xl tw:text-sm tw:leading-relaxed tw:text-foreground/75">
896
+ {{ group.description }}
897
+ </p>
898
+ }
899
+ </div>
900
+ <button
901
+ type="button"
902
+ [attr.aria-label]="closeLabel()"
903
+ (click)="close(true)"
904
+ class="tw:inline-flex tw:size-11 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-lg tw:text-foreground/75 tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-ring"
905
+ >
906
+ <ng-icon [svg]="closeIcon" size="18px" aria-hidden="true" />
907
+ </button>
908
+ </div>
909
+ <div class="tw:grid tw:grid-cols-2 tw:gap-3 tw:lg:grid-cols-3">
910
+ @for (item of group.items; track $index) {
911
+ <eg-layout-navigation-item
912
+ [item]="item"
913
+ appearance="card"
914
+ [itemClass]="itemClass()"
915
+ (selected)="close(true)"
916
+ />
917
+ }
918
+ </div>
919
+ </section>
920
+ }
921
+ }
922
+ </nav>
923
+ `, isInline: true, dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: EgLayoutNavigationItem, selector: "eg-layout-navigation-item", inputs: ["item", "itemClass", "appearance"], outputs: ["selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
924
+ }
925
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutFlyoutNavbar, decorators: [{
926
+ type: Component,
927
+ args: [{
928
+ selector: 'eg-layout-flyout-navbar',
929
+ imports: [NgIcon, EgLayoutNavigationItem],
930
+ changeDetection: ChangeDetectionStrategy.OnPush,
931
+ host: {
932
+ class: 'tw:relative tw:z-20 tw:block tw:min-w-0',
933
+ '(document:pointerdown)': 'closeOnOutsidePointer($event)',
934
+ '(focusout)': 'closeOnFocusOut($event)',
935
+ '(keydown.escape)': 'onEscape($event)',
936
+ },
937
+ template: `
938
+ <nav [attr.aria-label]="label()" [class]="navbarClasses()">
939
+ @for (group of groups(); track $index; let index = $index) {
940
+ <button
941
+ #trigger
942
+ type="button"
943
+ [id]="id + '-trigger-' + index"
944
+ [attr.aria-controls]="id + '-panel-' + index"
945
+ [attr.aria-expanded]="openIndex() === index"
946
+ [disabled]="!group.items.length"
947
+ (click)="toggle(index)"
948
+ (keydown)="onTriggerKeydown($event, index)"
949
+ [attr.data-active]="activeGroups()[index] ? '' : null"
950
+ [class]="
951
+ hlm(
952
+ 'tw:flex tw:min-h-11 tw:items-center tw:gap-2 tw:rounded-lg tw:px-3 tw:py-2 tw:text-left tw:text-sm tw:font-medium tw:text-foreground tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tw:disabled:cursor-not-allowed tw:disabled:opacity-50',
953
+ (openIndex() === index || activeGroups()[index]) && 'tw:bg-foreground/7 tw:font-semibold'
954
+ )
955
+ "
956
+ >
957
+ @if (group.icon) {
958
+ <ng-icon [svg]="group.icon" size="1rem" aria-hidden="true" />
959
+ }
960
+ {{ group.label }}
961
+ <ng-icon
962
+ [svg]="chevronIcon"
963
+ size="14px"
964
+ aria-hidden="true"
965
+ [class]="hlm('tw:shrink-0 tw:motion-safe:transition-transform', openIndex() === index && 'tw:rotate-180')"
966
+ />
967
+ </button>
968
+ @if (openIndex() === index) {
969
+ <section
970
+ #panel
971
+ [id]="id + '-panel-' + index"
972
+ [attr.aria-labelledby]="id + '-trigger-' + index"
973
+ data-slot="flyout-panel"
974
+ [class]="panelClasses()"
975
+ >
976
+ <div class="tw:mb-4 tw:flex tw:items-start tw:justify-between tw:gap-4">
977
+ <div class="tw:space-y-1">
978
+ <p class="tw:text-xs tw:font-semibold tw:uppercase tw:tracking-wider tw:text-foreground/75">
979
+ {{ group.label }}
980
+ </p>
981
+ @if (group.description) {
982
+ <p class="tw:max-w-2xl tw:text-sm tw:leading-relaxed tw:text-foreground/75">
983
+ {{ group.description }}
984
+ </p>
985
+ }
986
+ </div>
987
+ <button
988
+ type="button"
989
+ [attr.aria-label]="closeLabel()"
990
+ (click)="close(true)"
991
+ class="tw:inline-flex tw:size-11 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-lg tw:text-foreground/75 tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-ring"
992
+ >
993
+ <ng-icon [svg]="closeIcon" size="18px" aria-hidden="true" />
994
+ </button>
995
+ </div>
996
+ <div class="tw:grid tw:grid-cols-2 tw:gap-3 tw:lg:grid-cols-3">
997
+ @for (item of group.items; track $index) {
998
+ <eg-layout-navigation-item
999
+ [item]="item"
1000
+ appearance="card"
1001
+ [itemClass]="itemClass()"
1002
+ (selected)="close(true)"
1003
+ />
1004
+ }
1005
+ </div>
1006
+ </section>
1007
+ }
1008
+ }
1009
+ </nav>
1010
+ `,
1011
+ }]
1012
+ }], ctorParameters: () => [], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], navbarClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "navbarClass", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], triggers: [{ type: i0.ViewChildren, args: ['trigger', { isSignal: true }] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
1013
+
1014
+ /** Matches Tailwind's default `md` breakpoint. */
578
1015
  const EG_LAYOUT_SIMPLE_MOBILE_BREAKPOINT = '(max-width: 767.98px)';
579
- const commonLinkGroupClasses = 'tw:hidden tw:md:flex tw:space-x-4 tw:items-center';
580
- const commonLinkClasses = 'tw:text-left tw:text-secondary tw:visited:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline';
1016
+ /** Responsive application shell. All navigation surfaces share the same item model. */
581
1017
  class EgLayoutSimple {
582
- breakpointObserver;
583
1018
  destroyRef = inject(DestroyRef);
1019
+ breakpointObserver = inject(BreakpointObserver);
1020
+ router = inject(Router);
1021
+ instanceId = inject(_IdGenerator).getId('eg-layout-simple-');
1022
+ mainId = `${this.instanceId}-main`;
1023
+ mobileMenuId = `${this.instanceId}-mobile-menu`;
1024
+ sidebarId = `${this.instanceId}-sidebar`;
584
1025
  hlm = hlm;
1026
+ navigationMatchOptions = navigationMatchOptions;
585
1027
  menuIcon = lucideMenu;
1028
+ sidebarIcon = lucidePanelLeft;
1029
+ closeIcon = lucideX;
1030
+ chevronIcon = lucideChevronDown;
1031
+ mobileMenuTrigger = viewChild('mobileMenuTrigger', /* @ts-ignore */
1032
+ ...(ngDevMode ? [{ debugName: "mobileMenuTrigger" }] : /* istanbul ignore next */ []));
1033
+ mainContent = viewChild('mainContent', /* @ts-ignore */
1034
+ ...(ngDevMode ? [{ debugName: "mainContent" }] : /* istanbul ignore next */ []));
1035
+ sidebar = viewChild(EgLayoutSimpleSidebar, /* @ts-ignore */
1036
+ ...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
586
1037
  sidebarEnabled = input(false, /* @ts-ignore */
587
1038
  ...(ngDevMode ? [{ debugName: "sidebarEnabled" }] : /* istanbul ignore next */ []));
588
- sidebarTitle = input('Menu', /* @ts-ignore */
1039
+ sidebarTitle = input('Navigation', /* @ts-ignore */
589
1040
  ...(ngDevMode ? [{ debugName: "sidebarTitle" }] : /* istanbul ignore next */ []));
590
1041
  sidebarContent = input(/* @ts-ignore */
591
1042
  ...(ngDevMode ? [undefined, { debugName: "sidebarContent" }] : /* istanbul ignore next */ []));
592
- /** Accessible name for the icon-only sidebar trigger. */
593
1043
  sidebarToggleLabel = input('Open navigation sidebar', /* @ts-ignore */
594
1044
  ...(ngDevMode ? [{ debugName: "sidebarToggleLabel" }] : /* istanbul ignore next */ []));
595
- /** Accessible name for the icon-only mobile menu trigger. */
596
1045
  mobileMenuLabel = input('Open navigation menu', /* @ts-ignore */
597
1046
  ...(ngDevMode ? [{ debugName: "mobileMenuLabel" }] : /* istanbul ignore next */ []));
1047
+ mobileMenuCloseLabel = input('Close navigation menu', /* @ts-ignore */
1048
+ ...(ngDevMode ? [{ debugName: "mobileMenuCloseLabel" }] : /* istanbul ignore next */ []));
598
1049
  userMenuTrigger = input(/* @ts-ignore */
599
1050
  ...(ngDevMode ? [undefined, { debugName: "userMenuTrigger" }] : /* istanbul ignore next */ []));
600
- /** Menu data inputs */
601
- leftMenus = input([], /* @ts-ignore */
602
- ...(ngDevMode ? [{ debugName: "leftMenus" }] : /* istanbul ignore next */ []));
603
- leftMenuGroups = input([], /* @ts-ignore */
604
- ...(ngDevMode ? [{ debugName: "leftMenuGroups" }] : /* istanbul ignore next */ []));
605
- rightMenus = input([], /* @ts-ignore */
606
- ...(ngDevMode ? [{ debugName: "rightMenus" }] : /* istanbul ignore next */ []));
607
- topMenus = input([], /* @ts-ignore */
608
- ...(ngDevMode ? [{ debugName: "topMenus" }] : /* istanbul ignore next */ []));
609
- topSecondaryMenus = input([], /* @ts-ignore */
610
- ...(ngDevMode ? [{ debugName: "topSecondaryMenus" }] : /* istanbul ignore next */ []));
611
- userMenus = input([], /* @ts-ignore */
612
- ...(ngDevMode ? [{ debugName: "userMenus" }] : /* istanbul ignore next */ []));
613
- logo = input('assets/logo.png', /* @ts-ignore */
1051
+ userMenuLabel = input('Open account menu', /* @ts-ignore */
1052
+ ...(ngDevMode ? [{ debugName: "userMenuLabel" }] : /* istanbul ignore next */ []));
1053
+ /** Main header destinations; use `activeMatch: 'prefix'` for whole sections. */
1054
+ primaryNavigation = input([], /* @ts-ignore */
1055
+ ...(ngDevMode ? [{ debugName: "primaryNavigation" }] : /* istanbul ignore next */ []));
1056
+ navigationGroups = input([], /* @ts-ignore */
1057
+ ...(ngDevMode ? [{ debugName: "navigationGroups" }] : /* istanbul ignore next */ []));
1058
+ utilityNavigation = input([], /* @ts-ignore */
1059
+ ...(ngDevMode ? [{ debugName: "utilityNavigation" }] : /* istanbul ignore next */ []));
1060
+ sectionNavigation = input([], /* @ts-ignore */
1061
+ ...(ngDevMode ? [{ debugName: "sectionNavigation" }] : /* istanbul ignore next */ []));
1062
+ secondaryNavigationGroups = input([], /* @ts-ignore */
1063
+ ...(ngDevMode ? [{ debugName: "secondaryNavigationGroups" }] : /* istanbul ignore next */ []));
1064
+ /** Category navbar with wide card panels; mobile renders expandable groups. */
1065
+ flyoutNavigationGroups = input([], /* @ts-ignore */
1066
+ ...(ngDevMode ? [{ debugName: "flyoutNavigationGroups" }] : /* istanbul ignore next */ []));
1067
+ flyoutNavigationLabel = input('Fly-out navigation', /* @ts-ignore */
1068
+ ...(ngDevMode ? [{ debugName: "flyoutNavigationLabel" }] : /* istanbul ignore next */ []));
1069
+ flyoutCloseLabel = input('Close navigation panel', /* @ts-ignore */
1070
+ ...(ngDevMode ? [{ debugName: "flyoutCloseLabel" }] : /* istanbul ignore next */ []));
1071
+ userMenuSections = input([], /* @ts-ignore */
1072
+ ...(ngDevMode ? [{ debugName: "userMenuSections" }] : /* istanbul ignore next */ []));
1073
+ /** Optional image. Without it, the brand name is shown instead of a broken image. */
1074
+ logo = input('', /* @ts-ignore */
614
1075
  ...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
1076
+ brandName = input('Workspace', /* @ts-ignore */
1077
+ ...(ngDevMode ? [{ debugName: "brandName" }] : /* istanbul ignore next */ []));
615
1078
  logoLink = input('/', /* @ts-ignore */
616
1079
  ...(ngDevMode ? [{ debugName: "logoLink" }] : /* istanbul ignore next */ []));
617
- logoClass = input('', { ...(ngDevMode ? { debugName: "logoClass" } : /* istanbul ignore next */ {}), alias: 'logoClass' });
618
- headerClass = input('', { ...(ngDevMode ? { debugName: "headerClass" } : /* istanbul ignore next */ {}), alias: 'headerClass' });
619
- contentClass = input('', { ...(ngDevMode ? { debugName: "contentClass" } : /* istanbul ignore next */ {}), alias: 'contentClass' });
620
- contentBottomClass = input('', { ...(ngDevMode ? { debugName: "contentBottomClass" } : /* istanbul ignore next */ {}), alias: 'contentBottomClass' });
621
- /** Container class inputs */
622
- leftMenuClass = input('', { ...(ngDevMode ? { debugName: "leftMenuClass" } : /* istanbul ignore next */ {}), alias: 'leftClass' });
623
- rightMenuClass = input('', { ...(ngDevMode ? { debugName: "rightMenuClass" } : /* istanbul ignore next */ {}), alias: 'rightClass' });
624
- topMenuClass = input('', { ...(ngDevMode ? { debugName: "topMenuClass" } : /* istanbul ignore next */ {}), alias: 'topClass' });
625
- /** Link/button base class inputs */
626
- leftLinkClass = input('', { ...(ngDevMode ? { debugName: "leftLinkClass" } : /* istanbul ignore next */ {}), alias: 'leftLinkClass' });
627
- rightLinkClass = input('', { ...(ngDevMode ? { debugName: "rightLinkClass" } : /* istanbul ignore next */ {}), alias: 'rightLinkClass' });
628
- topLinkClass = input('', { ...(ngDevMode ? { debugName: "topLinkClass" } : /* istanbul ignore next */ {}), alias: 'topLinkClass' });
629
- searchEnabled = input(false, /* @ts-ignore */
630
- ...(ngDevMode ? [{ debugName: "searchEnabled" }] : /* istanbul ignore next */ []));
1080
+ logoClass = input('', /* @ts-ignore */
1081
+ ...(ngDevMode ? [{ debugName: "logoClass" }] : /* istanbul ignore next */ []));
1082
+ /** Disable for a shell preview embedded inside another page. */
1083
+ fullHeight = input(true, /* @ts-ignore */
1084
+ ...(ngDevMode ? [{ debugName: "fullHeight" }] : /* istanbul ignore next */ []));
1085
+ headerClass = input('', /* @ts-ignore */
1086
+ ...(ngDevMode ? [{ debugName: "headerClass" }] : /* istanbul ignore next */ []));
1087
+ contentClass = input('', /* @ts-ignore */
1088
+ ...(ngDevMode ? [{ debugName: "contentClass" }] : /* istanbul ignore next */ []));
1089
+ primaryNavigationClass = input('', /* @ts-ignore */
1090
+ ...(ngDevMode ? [{ debugName: "primaryNavigationClass" }] : /* istanbul ignore next */ []));
1091
+ utilityNavigationClass = input('', /* @ts-ignore */
1092
+ ...(ngDevMode ? [{ debugName: "utilityNavigationClass" }] : /* istanbul ignore next */ []));
1093
+ sectionNavigationClass = input('', /* @ts-ignore */
1094
+ ...(ngDevMode ? [{ debugName: "sectionNavigationClass" }] : /* istanbul ignore next */ []));
1095
+ secondaryNavigationClass = input('', /* @ts-ignore */
1096
+ ...(ngDevMode ? [{ debugName: "secondaryNavigationClass" }] : /* istanbul ignore next */ []));
1097
+ flyoutNavigationClass = input('', /* @ts-ignore */
1098
+ ...(ngDevMode ? [{ debugName: "flyoutNavigationClass" }] : /* istanbul ignore next */ []));
1099
+ flyoutPanelClass = input('', /* @ts-ignore */
1100
+ ...(ngDevMode ? [{ debugName: "flyoutPanelClass" }] : /* istanbul ignore next */ []));
1101
+ navigationItemClass = input('', /* @ts-ignore */
1102
+ ...(ngDevMode ? [{ debugName: "navigationItemClass" }] : /* istanbul ignore next */ []));
631
1103
  loading = input(false, /* @ts-ignore */
632
1104
  ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
633
- searchPlaceholderText = input('Select an page', /* @ts-ignore */
634
- ...(ngDevMode ? [{ debugName: "searchPlaceholderText" }] : /* istanbul ignore next */ []));
635
- searchEmptyText = input('No pages found', /* @ts-ignore */
1105
+ loadingText = input('Loading content…', /* @ts-ignore */
1106
+ ...(ngDevMode ? [{ debugName: "loadingText" }] : /* istanbul ignore next */ []));
1107
+ skipLinkText = input('Skip to content', /* @ts-ignore */
1108
+ ...(ngDevMode ? [{ debugName: "skipLinkText" }] : /* istanbul ignore next */ []));
1109
+ searchEnabled = input(false, /* @ts-ignore */
1110
+ ...(ngDevMode ? [{ debugName: "searchEnabled" }] : /* istanbul ignore next */ []));
1111
+ searchPlaceholder = input('Search pages…', /* @ts-ignore */
1112
+ ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
1113
+ searchEmptyText = input('No matching pages found.', /* @ts-ignore */
636
1114
  ...(ngDevMode ? [{ debugName: "searchEmptyText" }] : /* istanbul ignore next */ []));
637
- searchOptionTemplate = input(/* @ts-ignore */
638
- ...(ngDevMode ? [undefined, { debugName: "searchOptionTemplate" }] : /* istanbul ignore next */ []));
639
- searchLoaderFn = input(/* @ts-ignore */
640
- ...(ngDevMode ? [undefined, { debugName: "searchLoaderFn" }] : /* istanbul ignore next */ []));
641
- searchTransformValueToSearch = input(/* @ts-ignore */
642
- ...(ngDevMode ? [undefined, { debugName: "searchTransformValueToSearch" }] : /* istanbul ignore next */ []));
643
- searchOptionChange = output();
644
- _logoClass = computed(() => hlm('tw:h-10', this.logoClass()), /* @ts-ignore */
645
- ...(ngDevMode ? [{ debugName: "_logoClass" }] : /* istanbul ignore next */ []));
646
- _headerClass = computed(() => hlm('tw:px-4 tw:py-2 tw:flex tw:items-center tw:justify-between tw:bg-gray-100 tw:border-b tw:border-gray-300', this.headerClass()), /* @ts-ignore */
647
- ...(ngDevMode ? [{ debugName: "_headerClass" }] : /* istanbul ignore next */ []));
648
- _contentClass = computed(() => hlm('tw:p-4 tw:flex tw:flex-col tw:flex-1', this.contentClass()), /* @ts-ignore */
649
- ...(ngDevMode ? [{ debugName: "_contentClass" }] : /* istanbul ignore next */ []));
650
- _contentBottomClass = computed(() => hlm('tw:flex-1', this.contentBottomClass()), /* @ts-ignore */
651
- ...(ngDevMode ? [{ debugName: "_contentBottomClass" }] : /* istanbul ignore next */ []));
652
- /** Computed merged classes for containers */
653
- _computedLeftClass = computed(() => hlm(commonLinkGroupClasses, this.leftMenuClass()), /* @ts-ignore */
654
- ...(ngDevMode ? [{ debugName: "_computedLeftClass" }] : /* istanbul ignore next */ []));
655
- _computedRightClass = computed(() => hlm(commonLinkGroupClasses, this.rightMenuClass()), /* @ts-ignore */
656
- ...(ngDevMode ? [{ debugName: "_computedRightClass" }] : /* istanbul ignore next */ []));
657
- _computedTopClass = computed(() => hlm('tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-x-4 tw:gap-y-1 tw:px-4 tw:py-2 tw:bg-gray-50 tw:border-b tw:border-gray-200', this.topMenuClass()), /* @ts-ignore */
658
- ...(ngDevMode ? [{ debugName: "_computedTopClass" }] : /* istanbul ignore next */ []));
659
- _computedTopSecondaryClass = computed(() => hlm('tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-x-4 tw:gap-y-1 tw:px-4 tw:py-1.5 tw:bg-gray-100/60 tw:border-b tw:border-gray-200', this.topMenuClass()), /* @ts-ignore */
660
- ...(ngDevMode ? [{ debugName: "_computedTopSecondaryClass" }] : /* istanbul ignore next */ []));
661
- /** Computed merged classes for link/button elements */
662
- _computedLeftLinkClass = computed(() => hlm(commonLinkClasses, this.leftLinkClass()), /* @ts-ignore */
663
- ...(ngDevMode ? [{ debugName: "_computedLeftLinkClass" }] : /* istanbul ignore next */ []));
664
- _computedRightLinkClass = computed(() => hlm(commonLinkClasses, this.rightLinkClass()), /* @ts-ignore */
665
- ...(ngDevMode ? [{ debugName: "_computedRightLinkClass" }] : /* istanbul ignore next */ []));
666
- _computedTopLinkClass = computed(() => hlm('tw:text-secondary tw:visited:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline tw:text-sm', this.topLinkClass()), /* @ts-ignore */
667
- ...(ngDevMode ? [{ debugName: "_computedTopLinkClass" }] : /* istanbul ignore next */ []));
668
- mobileMenuItemClass = commonLinkClasses;
1115
+ searchErrorText = input('Search is unavailable. Please try again.', /* @ts-ignore */
1116
+ ...(ngDevMode ? [{ debugName: "searchErrorText" }] : /* istanbul ignore next */ []));
1117
+ searchResultTemplate = input(/* @ts-ignore */
1118
+ ...(ngDevMode ? [undefined, { debugName: "searchResultTemplate" }] : /* istanbul ignore next */ []));
1119
+ searchLoader = input(/* @ts-ignore */
1120
+ ...(ngDevMode ? [undefined, { debugName: "searchLoader" }] : /* istanbul ignore next */ []));
1121
+ searchResultLabel = input(/* @ts-ignore */
1122
+ ...(ngDevMode ? [undefined, { debugName: "searchResultLabel" }] : /* istanbul ignore next */ []));
1123
+ searchResultSelected = output();
669
1124
  footerEnabled = input(false, /* @ts-ignore */
670
1125
  ...(ngDevMode ? [{ debugName: "footerEnabled" }] : /* istanbul ignore next */ []));
671
- footerMenus = input([], /* @ts-ignore */
672
- ...(ngDevMode ? [{ debugName: "footerMenus" }] : /* istanbul ignore next */ []));
673
- footerMenuClass = input('', { ...(ngDevMode ? { debugName: "footerMenuClass" } : /* istanbul ignore next */ {}), alias: 'footerMenuClass' });
674
- footerLinkClass = input('', { ...(ngDevMode ? { debugName: "footerLinkClass" } : /* istanbul ignore next */ {}), alias: 'footerLinkClass' });
675
- footerContent = input('© 2024 My Company', /* @ts-ignore */
676
- ...(ngDevMode ? [{ debugName: "footerContent" }] : /* istanbul ignore next */ []));
677
- footerClass = input('', { ...(ngDevMode ? { debugName: "footerClass" } : /* istanbul ignore next */ {}), alias: 'footerClass' });
678
- _footerClass = computed(() => hlm('tw:px-4 tw:py-4 tw:bg-gray-100 tw:border-t tw:border-gray-300 tw:text-sm tw:text-gray-600', this.footerClass()), /* @ts-ignore */
679
- ...(ngDevMode ? [{ debugName: "_footerClass" }] : /* istanbul ignore next */ []));
680
- _computedFooterMenuClass = computed(() => hlm('tw:flex tw:flex-wrap tw:justify-center tw:space-x-4', this.footerMenuClass()), /* @ts-ignore */
681
- ...(ngDevMode ? [{ debugName: "_computedFooterMenuClass" }] : /* istanbul ignore next */ []));
682
- _computedFooterLinkClass = computed(() => hlm('tw:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline', this.footerLinkClass()), /* @ts-ignore */
683
- ...(ngDevMode ? [{ debugName: "_computedFooterLinkClass" }] : /* istanbul ignore next */ []));
684
- /** Mobile menu state */
1126
+ footerNavigation = input([], /* @ts-ignore */
1127
+ ...(ngDevMode ? [{ debugName: "footerNavigation" }] : /* istanbul ignore next */ []));
1128
+ footerText = input('', /* @ts-ignore */
1129
+ ...(ngDevMode ? [{ debugName: "footerText" }] : /* istanbul ignore next */ []));
1130
+ footerClass = input('', /* @ts-ignore */
1131
+ ...(ngDevMode ? [{ debugName: "footerClass" }] : /* istanbul ignore next */ []));
1132
+ logoClasses = computed(() => hlm('tw:h-8 tw:w-auto tw:max-w-40 tw:object-contain', this.logoClass()), /* @ts-ignore */
1133
+ ...(ngDevMode ? [{ debugName: "logoClasses" }] : /* istanbul ignore next */ []));
1134
+ headerClasses = computed(() => hlm('tw:flex tw:min-h-16 tw:flex-wrap tw:items-center tw:justify-between tw:gap-3 tw:border-b tw:border-border tw:bg-background tw:px-4 tw:py-3 tw:sm:px-6', this.headerClass()), /* @ts-ignore */
1135
+ ...(ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []));
1136
+ contentClasses = computed(() => hlm('tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:p-4 tw:outline-none tw:sm:p-6', this.contentClass()), /* @ts-ignore */
1137
+ ...(ngDevMode ? [{ debugName: "contentClasses" }] : /* istanbul ignore next */ []));
1138
+ primaryNavigationClasses = computed(() => hlm('tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-1', this.primaryNavigationClass()), /* @ts-ignore */
1139
+ ...(ngDevMode ? [{ debugName: "primaryNavigationClasses" }] : /* istanbul ignore next */ []));
1140
+ utilityNavigationClasses = computed(() => hlm('tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-1', this.utilityNavigationClass()), /* @ts-ignore */
1141
+ ...(ngDevMode ? [{ debugName: "utilityNavigationClasses" }] : /* istanbul ignore next */ []));
1142
+ sectionNavigationClasses = computed(() => hlm('tw:hidden tw:md:flex tw:items-center tw:gap-1 tw:overflow-x-auto tw:border-b tw:border-border tw:bg-background tw:px-4 tw:py-2 tw:sm:px-6', this.sectionNavigationClass()), /* @ts-ignore */
1143
+ ...(ngDevMode ? [{ debugName: "sectionNavigationClasses" }] : /* istanbul ignore next */ []));
1144
+ secondaryNavigationClasses = computed(() => hlm('tw:hidden tw:md:flex tw:items-center tw:gap-5 tw:overflow-x-auto tw:border-b tw:border-border tw:bg-foreground/3 tw:px-4 tw:py-2 tw:sm:px-6', this.secondaryNavigationClass()), /* @ts-ignore */
1145
+ ...(ngDevMode ? [{ debugName: "secondaryNavigationClasses" }] : /* istanbul ignore next */ []));
1146
+ footerClasses = computed(() => hlm('tw:flex tw:flex-wrap tw:items-center tw:justify-between tw:gap-x-6 tw:gap-y-2 tw:border-t tw:border-border tw:bg-background tw:px-4 tw:py-4 tw:text-sm tw:text-foreground/75 tw:sm:px-6', this.footerClass()), /* @ts-ignore */
1147
+ ...(ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []));
1148
+ iconButtonClasses = 'tw:inline-flex tw:size-11 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-lg tw:border tw:border-border tw:bg-background tw:text-foreground tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring';
685
1149
  mobileMenuOpen = signal(false, /* @ts-ignore */
686
1150
  ...(ngDevMode ? [{ debugName: "mobileMenuOpen" }] : /* istanbul ignore next */ []));
687
1151
  isMobile = signal(false, /* @ts-ignore */
688
1152
  ...(ngDevMode ? [{ debugName: "isMobile" }] : /* istanbul ignore next */ []));
689
- /** Expanded state of the sidebar sheet, kept in sync with BrnSheet state changes. */
690
1153
  sidebarOpen = signal(false, /* @ts-ignore */
691
1154
  ...(ngDevMode ? [{ debugName: "sidebarOpen" }] : /* istanbul ignore next */ []));
692
- constructor(breakpointObserver) {
693
- this.breakpointObserver = breakpointObserver;
1155
+ sidebarContext = { close: () => this.closeSidebar() };
1156
+ constructor() {
694
1157
  this.breakpointObserver
695
1158
  .observe([EG_LAYOUT_SIMPLE_MOBILE_BREAKPOINT])
696
1159
  .pipe(takeUntilDestroyed(this.destroyRef))
697
- .subscribe((result) => {
698
- this.isMobile.set(result.matches);
699
- });
700
- effect(() => {
701
- // Desktop navigation replaces the mobile menu above the breakpoint, so an
702
- // open mobile menu must not cross the boundary into desktop layout.
703
- if (!this.isMobile() && this.mobileMenuOpen()) {
1160
+ .subscribe(({ matches }) => {
1161
+ this.isMobile.set(matches);
1162
+ if (!matches)
704
1163
  this.mobileMenuOpen.set(false);
1164
+ });
1165
+ this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
1166
+ if (event instanceof NavigationEnd) {
1167
+ if (this.mobileMenuOpen())
1168
+ this.closeMobileMenu(true);
1169
+ this.closeSidebar();
705
1170
  }
706
1171
  });
707
1172
  effect((onCleanup) => {
708
- const sheet = this.viewchildSheetRef()?.viewchildSheetRef();
1173
+ const sheet = this.sidebar()?.sheet();
709
1174
  if (!sheet)
710
1175
  return;
711
1176
  this.sidebarOpen.set(sheet.stateComputed() === 'open');
712
1177
  const subscriptions = [
713
1178
  sheet.stateChanged.subscribe((state) => this.sidebarOpen.set(state === 'open')),
714
- // Escape/backdrop closes complete the dialog without a 'closed' state emission.
715
1179
  sheet.closed.subscribe(() => this.sidebarOpen.set(false)),
716
1180
  ];
717
1181
  onCleanup(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
@@ -720,43 +1184,47 @@ class EgLayoutSimple {
720
1184
  toggleMobileMenu() {
721
1185
  this.mobileMenuOpen.update((open) => !open);
722
1186
  }
723
- closeMobileMenu() {
1187
+ closeMobileMenu(restoreFocus = false) {
724
1188
  this.mobileMenuOpen.set(false);
1189
+ if (restoreFocus)
1190
+ this.mobileMenuTrigger()?.nativeElement.focus();
1191
+ }
1192
+ selectSearchResult(item) {
1193
+ this.closeMobileMenu(true);
1194
+ this.searchResultSelected.emit(item);
725
1195
  }
726
- onSearchOptionChange(value) {
727
- this.searchOptionChange.emit(value);
1196
+ focusContent(event) {
1197
+ event.preventDefault();
1198
+ this.mainContent()?.nativeElement.focus();
728
1199
  }
729
- viewchildSheetRef = viewChild(EgLayoutSimpleSidebar, /* @ts-ignore */
730
- ...(ngDevMode ? [{ debugName: "viewchildSheetRef" }] : /* istanbul ignore next */ []));
731
1200
  openSidebar() {
732
- this.viewchildSheetRef()?.openSheet();
1201
+ this.closeMobileMenu();
1202
+ this.sidebar()?.open();
733
1203
  }
734
1204
  closeSidebar() {
735
- this.viewchildSheetRef()?.closeSheet();
1205
+ this.sidebar()?.close();
736
1206
  }
737
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimple, deps: [{ token: i1$2.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
738
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimple, isStandalone: true, selector: "eg-layout-simple", inputs: { sidebarEnabled: { classPropertyName: "sidebarEnabled", publicName: "sidebarEnabled", isSignal: true, isRequired: false, transformFunction: null }, sidebarTitle: { classPropertyName: "sidebarTitle", publicName: "sidebarTitle", isSignal: true, isRequired: false, transformFunction: null }, sidebarContent: { classPropertyName: "sidebarContent", publicName: "sidebarContent", isSignal: true, isRequired: false, transformFunction: null }, sidebarToggleLabel: { classPropertyName: "sidebarToggleLabel", publicName: "sidebarToggleLabel", isSignal: true, isRequired: false, transformFunction: null }, mobileMenuLabel: { classPropertyName: "mobileMenuLabel", publicName: "mobileMenuLabel", isSignal: true, isRequired: false, transformFunction: null }, userMenuTrigger: { classPropertyName: "userMenuTrigger", publicName: "userMenuTrigger", isSignal: true, isRequired: false, transformFunction: null }, leftMenus: { classPropertyName: "leftMenus", publicName: "leftMenus", isSignal: true, isRequired: false, transformFunction: null }, leftMenuGroups: { classPropertyName: "leftMenuGroups", publicName: "leftMenuGroups", isSignal: true, isRequired: false, transformFunction: null }, rightMenus: { classPropertyName: "rightMenus", publicName: "rightMenus", isSignal: true, isRequired: false, transformFunction: null }, topMenus: { classPropertyName: "topMenus", publicName: "topMenus", isSignal: true, isRequired: false, transformFunction: null }, topSecondaryMenus: { classPropertyName: "topSecondaryMenus", publicName: "topSecondaryMenus", isSignal: true, isRequired: false, transformFunction: null }, userMenus: { classPropertyName: "userMenus", publicName: "userMenus", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, logoLink: { classPropertyName: "logoLink", publicName: "logoLink", isSignal: true, isRequired: false, transformFunction: null }, logoClass: { classPropertyName: "logoClass", publicName: "logoClass", isSignal: true, isRequired: false, transformFunction: null }, headerClass: { classPropertyName: "headerClass", publicName: "headerClass", isSignal: true, isRequired: false, transformFunction: null }, contentClass: { classPropertyName: "contentClass", publicName: "contentClass", isSignal: true, isRequired: false, transformFunction: null }, contentBottomClass: { classPropertyName: "contentBottomClass", publicName: "contentBottomClass", isSignal: true, isRequired: false, transformFunction: null }, leftMenuClass: { classPropertyName: "leftMenuClass", publicName: "leftClass", isSignal: true, isRequired: false, transformFunction: null }, rightMenuClass: { classPropertyName: "rightMenuClass", publicName: "rightClass", isSignal: true, isRequired: false, transformFunction: null }, topMenuClass: { classPropertyName: "topMenuClass", publicName: "topClass", isSignal: true, isRequired: false, transformFunction: null }, leftLinkClass: { classPropertyName: "leftLinkClass", publicName: "leftLinkClass", isSignal: true, isRequired: false, transformFunction: null }, rightLinkClass: { classPropertyName: "rightLinkClass", publicName: "rightLinkClass", isSignal: true, isRequired: false, transformFunction: null }, topLinkClass: { classPropertyName: "topLinkClass", publicName: "topLinkClass", isSignal: true, isRequired: false, transformFunction: null }, searchEnabled: { classPropertyName: "searchEnabled", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholderText: { classPropertyName: "searchPlaceholderText", publicName: "searchPlaceholderText", isSignal: true, isRequired: false, transformFunction: null }, searchEmptyText: { classPropertyName: "searchEmptyText", publicName: "searchEmptyText", isSignal: true, isRequired: false, transformFunction: null }, searchOptionTemplate: { classPropertyName: "searchOptionTemplate", publicName: "searchOptionTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchLoaderFn: { classPropertyName: "searchLoaderFn", publicName: "searchLoaderFn", isSignal: true, isRequired: false, transformFunction: null }, searchTransformValueToSearch: { classPropertyName: "searchTransformValueToSearch", publicName: "searchTransformValueToSearch", isSignal: true, isRequired: false, transformFunction: null }, footerEnabled: { classPropertyName: "footerEnabled", publicName: "footerEnabled", isSignal: true, isRequired: false, transformFunction: null }, footerMenus: { classPropertyName: "footerMenus", publicName: "footerMenus", isSignal: true, isRequired: false, transformFunction: null }, footerMenuClass: { classPropertyName: "footerMenuClass", publicName: "footerMenuClass", isSignal: true, isRequired: false, transformFunction: null }, footerLinkClass: { classPropertyName: "footerLinkClass", publicName: "footerLinkClass", isSignal: true, isRequired: false, transformFunction: null }, footerContent: { classPropertyName: "footerContent", publicName: "footerContent", isSignal: true, isRequired: false, transformFunction: null }, footerClass: { classPropertyName: "footerClass", publicName: "footerClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchOptionChange: "searchOptionChange" }, providers: [
739
- provideIcons({
740
- lucideMenu,
741
- }),
742
- ], viewQueries: [{ propertyName: "viewchildSheetRef", first: true, predicate: EgLayoutSimpleSidebar, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #menuIconTemplate>\n <ng-icon [svg]=\"menuIcon\" size=\"20px\" class=\"tw:[&_svg]:w-[inherit]! tw:[&_svg]:h-[inherit]!\" />\n</ng-template>\n\n<eg-layout-simple-sidebar\n [title]=\"sidebarTitle()\"\n [content]=\"sidebarContent()\"\n [contentContext]=\"{ close: closeSidebar.bind(this) }\"\n/>\n\n<div class=\"tw:flex tw:flex-col tw:min-h-screen\">\n <!-- Header -->\n <header [class]=\"_headerClass()\">\n <div class=\"tw:flex tw:items-center tw:space-x-4\">\n @if (sidebarEnabled()) {\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"icon\"\n [icon]=\"menuIconTemplate\"\n iconPosition=\"left\"\n class=\"tw:bg-transparent! tw:border-gray-400! tw:hover:border-gray-500!\"\n [attr.aria-label]=\"sidebarToggleLabel()\"\n [attr.aria-expanded]=\"sidebarOpen()\"\n aria-controls=\"eg-layout-simple-sidebar\"\n (click)=\"openSidebar()\"\n ></button>\n }\n\n <div class=\"logo\">\n <a [routerLink]=\"logoLink()\">\n <img [src]=\"logo()\" alt=\"Logo\" [class]=\"_logoClass()\" />\n </a>\n </div>\n <!-- Left menus (desktop) -->\n <nav [class]=\"_computedLeftClass()\">\n @for (item of leftMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } } @for (group of leftMenuGroups(); track $index) {\n <div class=\"tw:relative tw:group\">\n <button\n type=\"button\"\n class=\"tw:text-left tw:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline tw:py-1 tw:flex tw:items-center tw:gap-1\"\n >\n {{ group.label ?? 'Menu' }}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tw:h-3 tw:w-3\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n <div\n class=\"tw:absolute tw:left-0 tw:top-full tw:mt-1 tw:hidden tw:group-hover:flex tw:flex-col tw:min-w-[12rem] tw:bg-popover tw:text-popover-foreground tw:border tw:border-gray-200 tw:rounded-md tw:shadow-md tw:py-1 tw:z-50\"\n >\n @if (group.label) {\n <div class=\"tw:px-3 tw:py-1 tw:text-xs tw:font-semibold tw:text-muted-foreground\">{{ group.label }}</div>\n } @for (item of group.items; track item.label) { @if (item.link) {\n <a\n [routerLink]=\"item.link\"\n [class]=\"hlm('tw:px-3 tw:py-1.5 tw:text-sm tw:no-underline tw:hover:bg-secondary tw:cursor-pointer', item.class || '')\"\n >\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n (click)=\"item.action?.()\"\n [class]=\"hlm('tw:px-3 tw:py-1.5 tw:text-sm tw:text-left tw:hover:bg-secondary tw:cursor-pointer tw:bg-transparent tw:border-0 tw:w-full', item.class || '')\"\n >\n {{ item.label }}\n </button>\n } }\n </div>\n </div>\n }\n </nav>\n </div>\n\n <!-- Right menus (desktop) -->\n <nav [class]=\"_computedRightClass()\">\n @if (searchEnabled()) {\n <eg-generic-autocomplete\n [loaderFn]=\"searchLoaderFn()\"\n [transformValueToSearch]=\"searchTransformValueToSearch()\"\n [placeholderText]=\"searchPlaceholderText()\"\n [emptyText]=\"searchEmptyText()\"\n (optionChange)=\"onSearchOptionChange($event)\"\n ></eg-generic-autocomplete>\n } @for (item of rightMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } } @let uMenus = userMenus(); @if (uMenus && uMenus.length > 0) {\n <eg-layout-simple-user-menu [menus]=\"uMenus\" [menuTrigger]=\"userMenuTrigger()\" />\n }\n </nav>\n\n <!-- Mobile menu button -->\n <button\n (click)=\"toggleMobileMenu()\"\n class=\"tw:md:hidden tw:p-2 tw:text-gray-700 tw:hover:text-primary tw:focus:outline-none tw:cursor-pointer\"\n [attr.aria-label]=\"mobileMenuLabel()\"\n [attr.aria-expanded]=\"mobileMenuOpen()\"\n aria-controls=\"eg-layout-simple-mobile-menu\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tw:h-6 tw:w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n </header>\n\n @let _topMenus = leftMenus().concat(rightMenus()); @let _userMenus = userMenus(); @let _leftMenuGroups =\n leftMenuGroups(); @let _topMenuItems = topMenus(); @let _topSecondaryGroups = topSecondaryMenus();\n\n <!-- Top menus (desktop) -->\n @if (_topMenuItems.length > 0) {\n <nav [class]=\"_computedTopClass()\">\n @for (item of _topMenuItems; track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedTopLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <span [class]=\"hlm(_computedTopLinkClass(), item.class || '')\">{{ item.label }}</span>\n } }\n </nav>\n }\n\n <!-- Top secondary menus (desktop) \u2014 second row showing items grouped by parent label -->\n @if (_topSecondaryGroups.length > 0) {\n <nav [class]=\"_computedTopSecondaryClass()\">\n @for (group of _topSecondaryGroups; track group.label) {\n <span class=\"tw:flex tw:flex-wrap tw:items-center tw:gap-x-3\">\n @if (group.label) {\n <span class=\"tw:text-xs tw:font-semibold tw:uppercase tw:text-muted-foreground\">{{ group.label }}</span>\n } @for (item of group.items; track item.label) { @if (item.link) {\n <a\n [routerLink]=\"item.link\"\n [class]=\"hlm(_computedTopLinkClass(), 'tw:text-xs tw:hover:underline', item.class || '')\"\n >\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n (click)=\"item.action?.()\"\n [class]=\"hlm(_computedTopLinkClass(), 'tw:text-xs tw:hover:underline', item.class || '')\"\n >\n {{ item.label }}\n </button>\n } }\n </span>\n }\n </nav>\n }\n\n <!-- Mobile menu -->\n @if (isMobile() && mobileMenuOpen()) {\n <div id=\"eg-layout-simple-mobile-menu\" class=\"tw:w-full tw:border-none\" (keydown.escape)=\"closeMobileMenu()\">\n @if (_topMenuItems.length > 0) {\n <eg-layout-simple-mobile-menu-group [items]=\"_topMenuItems\" (itemClick)=\"closeMobileMenu()\" />\n } @for (group of _topSecondaryGroups; track group.label) { @if (group.items && group.items.length > 0) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n } }\n\n <eg-layout-simple-mobile-menu-group [items]=\"_topMenus\" (itemClick)=\"closeMobileMenu()\" />\n\n @for (group of _leftMenuGroups; track $index) { @if (group.items && group.items.length > 0) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n } } @if ((_topMenus.length > 0 || _leftMenuGroups.length > 0) && _userMenus.length > 0) {\n <hr class=\"tw:border-gray-300 tw:my-2\" />\n } @for (section of userMenus(); track section.label) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"section.items\"\n [label]=\"section.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n\n @if (section.separator) {\n <hr class=\"tw:border-gray-300 tw:my-2\" />\n } }\n </div>\n }\n\n <!-- Main content -->\n <main [class]=\"_contentClass()\">\n @if (!loading()) {\n <div class=\"tw:flex tw:items-center tw:justify-center tw:h-full eg-layout-simple-main-content\">\n <ng-content />\n </div>\n }\n <div [class]=\"_contentBottomClass()\"></div>\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"_footerClass()\">\n <nav [class]=\"_computedFooterMenuClass()\">\n @for (item of footerMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } }\n </nav>\n\n <div class=\"tw:mt-2 tw:text-center\">{{ footerContent() }}</div>\n </footer>\n }\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: EgLayoutSimpleUserMenu, selector: "eg-layout-simple-user-menu", inputs: ["menus", "menuTrigger"] }, { kind: "component", type: EgLayoutSimpleSidebar, selector: "eg-layout-simple-sidebar", inputs: ["side", "title", "content", "contentContext"] }, { kind: "component", type: EgLayoutSimpleMobileMenuGroup, selector: "eg-layout-simple-mobile-menu-group", inputs: ["label", "items"], outputs: ["itemClick"] }, { kind: "component", type: EgGenericAutocomplete, selector: "eg-generic-autocomplete", inputs: ["placeholderText", "emptyText", "loaderFn", "transformValueToSearch"], outputs: ["optionChange"] }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }] });
1207
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimple, deps: [], target: i0.ɵɵFactoryTarget.Component });
1208
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSimple, isStandalone: true, selector: "eg-layout-simple", inputs: { sidebarEnabled: { classPropertyName: "sidebarEnabled", publicName: "sidebarEnabled", isSignal: true, isRequired: false, transformFunction: null }, sidebarTitle: { classPropertyName: "sidebarTitle", publicName: "sidebarTitle", isSignal: true, isRequired: false, transformFunction: null }, sidebarContent: { classPropertyName: "sidebarContent", publicName: "sidebarContent", isSignal: true, isRequired: false, transformFunction: null }, sidebarToggleLabel: { classPropertyName: "sidebarToggleLabel", publicName: "sidebarToggleLabel", isSignal: true, isRequired: false, transformFunction: null }, mobileMenuLabel: { classPropertyName: "mobileMenuLabel", publicName: "mobileMenuLabel", isSignal: true, isRequired: false, transformFunction: null }, mobileMenuCloseLabel: { classPropertyName: "mobileMenuCloseLabel", publicName: "mobileMenuCloseLabel", isSignal: true, isRequired: false, transformFunction: null }, userMenuTrigger: { classPropertyName: "userMenuTrigger", publicName: "userMenuTrigger", isSignal: true, isRequired: false, transformFunction: null }, userMenuLabel: { classPropertyName: "userMenuLabel", publicName: "userMenuLabel", isSignal: true, isRequired: false, transformFunction: null }, primaryNavigation: { classPropertyName: "primaryNavigation", publicName: "primaryNavigation", isSignal: true, isRequired: false, transformFunction: null }, navigationGroups: { classPropertyName: "navigationGroups", publicName: "navigationGroups", isSignal: true, isRequired: false, transformFunction: null }, utilityNavigation: { classPropertyName: "utilityNavigation", publicName: "utilityNavigation", isSignal: true, isRequired: false, transformFunction: null }, sectionNavigation: { classPropertyName: "sectionNavigation", publicName: "sectionNavigation", isSignal: true, isRequired: false, transformFunction: null }, secondaryNavigationGroups: { classPropertyName: "secondaryNavigationGroups", publicName: "secondaryNavigationGroups", isSignal: true, isRequired: false, transformFunction: null }, flyoutNavigationGroups: { classPropertyName: "flyoutNavigationGroups", publicName: "flyoutNavigationGroups", isSignal: true, isRequired: false, transformFunction: null }, flyoutNavigationLabel: { classPropertyName: "flyoutNavigationLabel", publicName: "flyoutNavigationLabel", isSignal: true, isRequired: false, transformFunction: null }, flyoutCloseLabel: { classPropertyName: "flyoutCloseLabel", publicName: "flyoutCloseLabel", isSignal: true, isRequired: false, transformFunction: null }, userMenuSections: { classPropertyName: "userMenuSections", publicName: "userMenuSections", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, brandName: { classPropertyName: "brandName", publicName: "brandName", isSignal: true, isRequired: false, transformFunction: null }, logoLink: { classPropertyName: "logoLink", publicName: "logoLink", isSignal: true, isRequired: false, transformFunction: null }, logoClass: { classPropertyName: "logoClass", publicName: "logoClass", isSignal: true, isRequired: false, transformFunction: null }, fullHeight: { classPropertyName: "fullHeight", publicName: "fullHeight", isSignal: true, isRequired: false, transformFunction: null }, headerClass: { classPropertyName: "headerClass", publicName: "headerClass", isSignal: true, isRequired: false, transformFunction: null }, contentClass: { classPropertyName: "contentClass", publicName: "contentClass", isSignal: true, isRequired: false, transformFunction: null }, primaryNavigationClass: { classPropertyName: "primaryNavigationClass", publicName: "primaryNavigationClass", isSignal: true, isRequired: false, transformFunction: null }, utilityNavigationClass: { classPropertyName: "utilityNavigationClass", publicName: "utilityNavigationClass", isSignal: true, isRequired: false, transformFunction: null }, sectionNavigationClass: { classPropertyName: "sectionNavigationClass", publicName: "sectionNavigationClass", isSignal: true, isRequired: false, transformFunction: null }, secondaryNavigationClass: { classPropertyName: "secondaryNavigationClass", publicName: "secondaryNavigationClass", isSignal: true, isRequired: false, transformFunction: null }, flyoutNavigationClass: { classPropertyName: "flyoutNavigationClass", publicName: "flyoutNavigationClass", isSignal: true, isRequired: false, transformFunction: null }, flyoutPanelClass: { classPropertyName: "flyoutPanelClass", publicName: "flyoutPanelClass", isSignal: true, isRequired: false, transformFunction: null }, navigationItemClass: { classPropertyName: "navigationItemClass", publicName: "navigationItemClass", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, skipLinkText: { classPropertyName: "skipLinkText", publicName: "skipLinkText", isSignal: true, isRequired: false, transformFunction: null }, searchEnabled: { classPropertyName: "searchEnabled", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, searchEmptyText: { classPropertyName: "searchEmptyText", publicName: "searchEmptyText", isSignal: true, isRequired: false, transformFunction: null }, searchErrorText: { classPropertyName: "searchErrorText", publicName: "searchErrorText", isSignal: true, isRequired: false, transformFunction: null }, searchResultTemplate: { classPropertyName: "searchResultTemplate", publicName: "searchResultTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchLoader: { classPropertyName: "searchLoader", publicName: "searchLoader", isSignal: true, isRequired: false, transformFunction: null }, searchResultLabel: { classPropertyName: "searchResultLabel", publicName: "searchResultLabel", isSignal: true, isRequired: false, transformFunction: null }, footerEnabled: { classPropertyName: "footerEnabled", publicName: "footerEnabled", isSignal: true, isRequired: false, transformFunction: null }, footerNavigation: { classPropertyName: "footerNavigation", publicName: "footerNavigation", isSignal: true, isRequired: false, transformFunction: null }, footerText: { classPropertyName: "footerText", publicName: "footerText", isSignal: true, isRequired: false, transformFunction: null }, footerClass: { classPropertyName: "footerClass", publicName: "footerClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchResultSelected: "searchResultSelected" }, host: { classAttribute: "tw:block tw:min-w-0" }, viewQueries: [{ propertyName: "mobileMenuTrigger", first: true, predicate: ["mobileMenuTrigger"], descendants: true, isSignal: true }, { propertyName: "mainContent", first: true, predicate: ["mainContent"], descendants: true, isSignal: true }, { propertyName: "sidebar", first: true, predicate: EgLayoutSimpleSidebar, descendants: true, isSignal: true }], ngImport: i0, template: "@if (sidebarEnabled()) {\n<eg-layout-simple-sidebar\n [panelId]=\"sidebarId\"\n [title]=\"sidebarTitle()\"\n [content]=\"sidebarContent()\"\n [contentContext]=\"sidebarContext\"\n/>\n}\n\n<div\n [class]=\"hlm('tw:relative tw:isolate tw:flex tw:min-w-0 tw:flex-col tw:bg-background tw:text-foreground', fullHeight() && 'tw:min-h-dvh')\"\n>\n <a\n [href]=\"'#' + mainId\"\n (click)=\"focusContent($event)\"\n class=\"tw:sr-only tw:focus:not-sr-only tw:focus:absolute tw:focus:left-4 tw:focus:top-2 tw:focus:z-50 tw:focus:rounded-lg tw:focus:bg-background tw:focus:px-4 tw:focus:py-3 tw:focus:text-foreground tw:focus:outline-2 tw:focus:outline-ring\"\n >{{ skipLinkText() }}</a\n >\n\n <header [class]=\"headerClasses()\">\n <div class=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:gap-3 tw:md:flex-none tw:md:flex-wrap\">\n @if (sidebarEnabled()) {\n <button\n type=\"button\"\n [class]=\"iconButtonClasses\"\n [attr.aria-label]=\"sidebarToggleLabel()\"\n [attr.aria-expanded]=\"sidebarOpen()\"\n [attr.aria-controls]=\"sidebarId\"\n (click)=\"openSidebar()\"\n >\n <ng-icon [svg]=\"sidebarIcon\" size=\"20px\" aria-hidden=\"true\" />\n </button>\n }\n <a\n [routerLink]=\"logoLink()\"\n [attr.aria-label]=\"brandName() + ' home'\"\n class=\"tw:flex tw:min-h-11 tw:min-w-0 tw:items-center tw:gap-2.5 tw:rounded-lg tw:pr-2 tw:text-foreground tw:no-underline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring\"\n >\n @if (logo()) { <img [src]=\"logo()\" alt=\"\" [class]=\"logoClasses()\" /> }\n <span class=\"tw:truncate tw:text-base tw:font-semibold tw:tracking-tight\">{{ brandName() }}</span>\n </a>\n <nav aria-label=\"Primary navigation\" [class]=\"primaryNavigationClasses()\">\n @for (item of primaryNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n } @for (group of navigationGroups(); track $index) {\n <button\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"groupMenu\"\n class=\"tw:flex tw:min-h-11 tw:items-center tw:gap-2 tw:rounded-lg tw:px-3 tw:text-sm tw:font-medium tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-ring\"\n >\n {{ group.label || 'More' }} <ng-icon [svg]=\"chevronIcon\" size=\"14px\" aria-hidden=\"true\" />\n </button>\n <ng-template #groupMenu>\n <div hlmDropdownMenu class=\"tw:w-60\">\n @for (item of group.items; track $index) { @if (item.link && !item.disabled) {\n <a\n hlmDropdownMenuItem\n [routerLink]=\"item.link\"\n routerLinkActive=\"tw:bg-foreground/10 tw:font-semibold\"\n [routerLinkActiveOptions]=\"navigationMatchOptions(item)\"\n ariaCurrentWhenActive=\"page\"\n [class]=\"hlm('tw:min-h-11 tw:gap-2 tw:no-underline', item.class)\"\n >\n @if (item.icon) { <ng-icon [svg]=\"item.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n hlmDropdownMenuItem\n [disabled]=\"item.disabled || !item.action\"\n [class]=\"hlm('tw:min-h-11 tw:gap-2', item.class)\"\n (click)=\"item.action?.()\"\n >\n @if (item.icon) { <ng-icon [svg]=\"item.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ item.label }}\n </button>\n } }\n </div>\n </ng-template>\n }\n </nav>\n </div>\n\n <div class=\"tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-3\">\n @if (searchEnabled() && !isMobile()) { <ng-container [ngTemplateOutlet]=\"searchTemplate\" /> } @if\n (utilityNavigation().length) {\n <nav aria-label=\"Utility navigation\" [class]=\"utilityNavigationClasses()\">\n @for (item of utilityNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n }\n </nav>\n } @if (userMenuSections().length) {\n <eg-layout-simple-user-menu\n [sections]=\"userMenuSections()\"\n [triggerTemplate]=\"userMenuTrigger()\"\n [triggerLabel]=\"userMenuLabel()\"\n />\n }\n </div>\n\n <button\n #mobileMenuTrigger\n type=\"button\"\n (click)=\"toggleMobileMenu()\"\n [class]=\"hlm(iconButtonClasses, 'tw:md:hidden')\"\n [attr.aria-label]=\"mobileMenuOpen() ? mobileMenuCloseLabel() : mobileMenuLabel()\"\n [attr.aria-expanded]=\"mobileMenuOpen()\"\n [attr.aria-controls]=\"mobileMenuId\"\n >\n <ng-icon [svg]=\"mobileMenuOpen() ? closeIcon : menuIcon\" size=\"20px\" aria-hidden=\"true\" />\n </button>\n </header>\n\n @if (sectionNavigation().length) {\n <nav aria-label=\"Section navigation\" [class]=\"sectionNavigationClasses()\">\n @for (item of sectionNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n }\n </nav>\n } @if (flyoutNavigationGroups().length && !isMobile()) {\n <eg-layout-flyout-navbar\n class=\"tw:hidden tw:md:block\"\n [groups]=\"flyoutNavigationGroups()\"\n [label]=\"flyoutNavigationLabel()\"\n [closeLabel]=\"flyoutCloseLabel()\"\n [navbarClass]=\"flyoutNavigationClass()\"\n [panelClass]=\"flyoutPanelClass()\"\n [itemClass]=\"navigationItemClass()\"\n />\n } @if (secondaryNavigationGroups().length) {\n <nav aria-label=\"Secondary navigation\" [class]=\"secondaryNavigationClasses()\" tabindex=\"0\">\n @for (group of secondaryNavigationGroups(); track $index; let first = $first) {\n <div\n [class]=\"hlm('tw:flex tw:shrink-0 tw:items-center tw:gap-1', !first && 'tw:border-l tw:border-border tw:pl-5')\"\n >\n @if (group.label) {\n <span class=\"tw:mr-2 tw:text-xs tw:font-semibold tw:text-foreground/75 tw:whitespace-nowrap\"\n >{{ group.label }}</span\n >\n } @for (item of group.items; track $index) {\n <eg-layout-navigation-item\n [item]=\"item\"\n [itemClass]=\"hlm('tw:rounded-full tw:whitespace-nowrap', navigationItemClass())\"\n />\n }\n </div>\n }\n </nav>\n } @if (isMobile() && mobileMenuOpen()) {\n <nav\n [id]=\"mobileMenuId\"\n aria-label=\"Mobile navigation\"\n (keydown.escape)=\"closeMobileMenu(true); $event.stopPropagation()\"\n class=\"tw:md:hidden tw:max-h-[70dvh] tw:overflow-y-auto tw:overscroll-contain tw:space-y-4 tw:border-b tw:border-border tw:bg-background tw:p-4\"\n >\n @if (searchEnabled()) { <ng-container [ngTemplateOutlet]=\"searchTemplate\" /> }\n <eg-layout-simple-mobile-menu-group [items]=\"primaryNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @for (group of navigationGroups(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n <eg-layout-simple-mobile-menu-group [items]=\"sectionNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @for (group of flyoutNavigationGroups(); track $index) {\n <details class=\"tw:group/flyout tw:rounded-xl tw:border tw:border-border tw:bg-foreground/3\">\n <summary\n class=\"tw:flex tw:min-h-11 tw:list-none tw:items-center tw:justify-between tw:gap-2 tw:rounded-xl tw:px-3 tw:py-3 tw:text-sm tw:font-semibold tw:cursor-pointer tw:focus-visible:outline-2 tw:focus-visible:outline-ring tw:[&::-webkit-details-marker]:hidden\"\n >\n <span class=\"tw:flex tw:items-center tw:gap-2\">\n @if (group.icon) { <ng-icon [svg]=\"group.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ group.label }}\n </span>\n <ng-icon\n [svg]=\"chevronIcon\"\n size=\"14px\"\n aria-hidden=\"true\"\n class=\"tw:shrink-0 tw:group-open/flyout:rotate-180\"\n />\n </summary>\n <div class=\"tw:space-y-2 tw:border-t tw:border-border tw:p-2\">\n @if (group.description) {\n <p class=\"tw:px-3 tw:py-2 tw:text-sm tw:text-foreground/75\">{{ group.description }}</p>\n } @for (item of group.items; track $index) {\n <eg-layout-navigation-item\n [item]=\"item\"\n appearance=\"card\"\n [itemClass]=\"navigationItemClass()\"\n (selected)=\"closeMobileMenu(true)\"\n />\n }\n </div>\n </details>\n } @for (group of secondaryNavigationGroups(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n <eg-layout-simple-mobile-menu-group [items]=\"utilityNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @if (userMenuSections().length) {\n <div class=\"tw:space-y-4 tw:border-t tw:border-border tw:pt-4\">\n @for (section of userMenuSections(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"section.items\"\n [label]=\"section.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n </div>\n }\n </nav>\n }\n\n <main #mainContent [id]=\"mainId\" tabindex=\"-1\" [attr.aria-busy]=\"loading()\" [class]=\"contentClasses()\">\n @if (loading()) {\n <div\n role=\"status\"\n class=\"tw:flex tw:min-h-48 tw:flex-1 tw:items-center tw:justify-center tw:gap-3 tw:text-sm tw:text-foreground/75\"\n >\n <span\n aria-hidden=\"true\"\n class=\"tw:size-5 tw:rounded-full tw:border-2 tw:border-border tw:border-t-foreground tw:motion-safe:animate-spin\"\n ></span>\n {{ loadingText() }}\n </div>\n }\n <div\n [hidden]=\"loading()\"\n [style.display]=\"loading() ? 'none' : null\"\n class=\"tw:w-full tw:min-w-0 eg-layout-simple-main-content\"\n >\n <ng-content />\n </div>\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"footerClasses()\">\n @if (footerText()) {\n <p>{{ footerText() }}</p>\n } @if (footerNavigation().length) {\n <nav aria-label=\"Footer navigation\" class=\"tw:flex tw:flex-wrap tw:items-center tw:gap-1\">\n @for (item of footerNavigation(); track $index) { <eg-layout-navigation-item [item]=\"item\" /> }\n </nav>\n }\n </footer>\n }\n</div>\n\n<ng-template #searchTemplate>\n <eg-layout-search\n [loader]=\"searchLoader()\"\n [resultLabel]=\"searchResultLabel()\"\n [placeholder]=\"searchPlaceholder()\"\n [emptyText]=\"searchEmptyText()\"\n [errorText]=\"searchErrorText()\"\n [resultTemplate]=\"searchResultTemplate()\"\n (resultSelected)=\"selectSearchResult($event)\"\n />\n</ng-template>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: EgLayoutSimpleUserMenu, selector: "eg-layout-simple-user-menu", inputs: ["sections", "triggerTemplate", "triggerLabel"] }, { kind: "component", type: EgLayoutSimpleSidebar, selector: "eg-layout-simple-sidebar", inputs: ["panelId", "title", "content", "contentContext"] }, { kind: "component", type: EgLayoutSimpleMobileMenuGroup, selector: "eg-layout-simple-mobile-menu-group", inputs: ["label", "items"], outputs: ["itemSelected"] }, { kind: "component", type: EgLayoutSearch, selector: "eg-layout-search", inputs: ["placeholder", "emptyText", "errorText", "loadingText", "retryText", "loader", "resultLabel", "resultTemplate"], outputs: ["resultSelected"] }, { kind: "component", type: EgLayoutNavigationItem, selector: "eg-layout-navigation-item", inputs: ["item", "itemClass", "appearance"], outputs: ["selected"] }, { kind: "component", type: EgLayoutFlyoutNavbar, selector: "eg-layout-flyout-navbar", inputs: ["groups", "label", "closeLabel", "navbarClass", "panelClass", "itemClass"] }, { kind: "directive", type: HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: HlmDropdownMenuItem, selector: "[hlmDropdownMenuItem],hlm-dropdown-menu-item", inputs: ["disabled", "variant", "inset"] }, { kind: "directive", type: HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
743
1209
  }
744
1210
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSimple, decorators: [{
745
1211
  type: Component,
746
- args: [{ selector: 'eg-layout-simple', standalone: true, imports: [
1212
+ args: [{ selector: 'eg-layout-simple', imports: [
747
1213
  RouterLink,
1214
+ RouterLinkActive,
1215
+ NgTemplateOutlet,
1216
+ NgIcon,
748
1217
  EgLayoutSimpleUserMenu,
749
1218
  EgLayoutSimpleSidebar,
750
1219
  EgLayoutSimpleMobileMenuGroup,
751
- EgGenericAutocomplete,
752
- HlmButton,
753
- NgIcon,
754
- ], providers: [
755
- provideIcons({
756
- lucideMenu,
757
- }),
758
- ], template: "<ng-template #menuIconTemplate>\n <ng-icon [svg]=\"menuIcon\" size=\"20px\" class=\"tw:[&_svg]:w-[inherit]! tw:[&_svg]:h-[inherit]!\" />\n</ng-template>\n\n<eg-layout-simple-sidebar\n [title]=\"sidebarTitle()\"\n [content]=\"sidebarContent()\"\n [contentContext]=\"{ close: closeSidebar.bind(this) }\"\n/>\n\n<div class=\"tw:flex tw:flex-col tw:min-h-screen\">\n <!-- Header -->\n <header [class]=\"_headerClass()\">\n <div class=\"tw:flex tw:items-center tw:space-x-4\">\n @if (sidebarEnabled()) {\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"icon\"\n [icon]=\"menuIconTemplate\"\n iconPosition=\"left\"\n class=\"tw:bg-transparent! tw:border-gray-400! tw:hover:border-gray-500!\"\n [attr.aria-label]=\"sidebarToggleLabel()\"\n [attr.aria-expanded]=\"sidebarOpen()\"\n aria-controls=\"eg-layout-simple-sidebar\"\n (click)=\"openSidebar()\"\n ></button>\n }\n\n <div class=\"logo\">\n <a [routerLink]=\"logoLink()\">\n <img [src]=\"logo()\" alt=\"Logo\" [class]=\"_logoClass()\" />\n </a>\n </div>\n <!-- Left menus (desktop) -->\n <nav [class]=\"_computedLeftClass()\">\n @for (item of leftMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } } @for (group of leftMenuGroups(); track $index) {\n <div class=\"tw:relative tw:group\">\n <button\n type=\"button\"\n class=\"tw:text-left tw:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline tw:py-1 tw:flex tw:items-center tw:gap-1\"\n >\n {{ group.label ?? 'Menu' }}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tw:h-3 tw:w-3\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n <div\n class=\"tw:absolute tw:left-0 tw:top-full tw:mt-1 tw:hidden tw:group-hover:flex tw:flex-col tw:min-w-[12rem] tw:bg-popover tw:text-popover-foreground tw:border tw:border-gray-200 tw:rounded-md tw:shadow-md tw:py-1 tw:z-50\"\n >\n @if (group.label) {\n <div class=\"tw:px-3 tw:py-1 tw:text-xs tw:font-semibold tw:text-muted-foreground\">{{ group.label }}</div>\n } @for (item of group.items; track item.label) { @if (item.link) {\n <a\n [routerLink]=\"item.link\"\n [class]=\"hlm('tw:px-3 tw:py-1.5 tw:text-sm tw:no-underline tw:hover:bg-secondary tw:cursor-pointer', item.class || '')\"\n >\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n (click)=\"item.action?.()\"\n [class]=\"hlm('tw:px-3 tw:py-1.5 tw:text-sm tw:text-left tw:hover:bg-secondary tw:cursor-pointer tw:bg-transparent tw:border-0 tw:w-full', item.class || '')\"\n >\n {{ item.label }}\n </button>\n } }\n </div>\n </div>\n }\n </nav>\n </div>\n\n <!-- Right menus (desktop) -->\n <nav [class]=\"_computedRightClass()\">\n @if (searchEnabled()) {\n <eg-generic-autocomplete\n [loaderFn]=\"searchLoaderFn()\"\n [transformValueToSearch]=\"searchTransformValueToSearch()\"\n [placeholderText]=\"searchPlaceholderText()\"\n [emptyText]=\"searchEmptyText()\"\n (optionChange)=\"onSearchOptionChange($event)\"\n ></eg-generic-autocomplete>\n } @for (item of rightMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } } @let uMenus = userMenus(); @if (uMenus && uMenus.length > 0) {\n <eg-layout-simple-user-menu [menus]=\"uMenus\" [menuTrigger]=\"userMenuTrigger()\" />\n }\n </nav>\n\n <!-- Mobile menu button -->\n <button\n (click)=\"toggleMobileMenu()\"\n class=\"tw:md:hidden tw:p-2 tw:text-gray-700 tw:hover:text-primary tw:focus:outline-none tw:cursor-pointer\"\n [attr.aria-label]=\"mobileMenuLabel()\"\n [attr.aria-expanded]=\"mobileMenuOpen()\"\n aria-controls=\"eg-layout-simple-mobile-menu\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tw:h-6 tw:w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n </header>\n\n @let _topMenus = leftMenus().concat(rightMenus()); @let _userMenus = userMenus(); @let _leftMenuGroups =\n leftMenuGroups(); @let _topMenuItems = topMenus(); @let _topSecondaryGroups = topSecondaryMenus();\n\n <!-- Top menus (desktop) -->\n @if (_topMenuItems.length > 0) {\n <nav [class]=\"_computedTopClass()\">\n @for (item of _topMenuItems; track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedTopLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <span [class]=\"hlm(_computedTopLinkClass(), item.class || '')\">{{ item.label }}</span>\n } }\n </nav>\n }\n\n <!-- Top secondary menus (desktop) \u2014 second row showing items grouped by parent label -->\n @if (_topSecondaryGroups.length > 0) {\n <nav [class]=\"_computedTopSecondaryClass()\">\n @for (group of _topSecondaryGroups; track group.label) {\n <span class=\"tw:flex tw:flex-wrap tw:items-center tw:gap-x-3\">\n @if (group.label) {\n <span class=\"tw:text-xs tw:font-semibold tw:uppercase tw:text-muted-foreground\">{{ group.label }}</span>\n } @for (item of group.items; track item.label) { @if (item.link) {\n <a\n [routerLink]=\"item.link\"\n [class]=\"hlm(_computedTopLinkClass(), 'tw:text-xs tw:hover:underline', item.class || '')\"\n >\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n (click)=\"item.action?.()\"\n [class]=\"hlm(_computedTopLinkClass(), 'tw:text-xs tw:hover:underline', item.class || '')\"\n >\n {{ item.label }}\n </button>\n } }\n </span>\n }\n </nav>\n }\n\n <!-- Mobile menu -->\n @if (isMobile() && mobileMenuOpen()) {\n <div id=\"eg-layout-simple-mobile-menu\" class=\"tw:w-full tw:border-none\" (keydown.escape)=\"closeMobileMenu()\">\n @if (_topMenuItems.length > 0) {\n <eg-layout-simple-mobile-menu-group [items]=\"_topMenuItems\" (itemClick)=\"closeMobileMenu()\" />\n } @for (group of _topSecondaryGroups; track group.label) { @if (group.items && group.items.length > 0) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n } }\n\n <eg-layout-simple-mobile-menu-group [items]=\"_topMenus\" (itemClick)=\"closeMobileMenu()\" />\n\n @for (group of _leftMenuGroups; track $index) { @if (group.items && group.items.length > 0) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n } } @if ((_topMenus.length > 0 || _leftMenuGroups.length > 0) && _userMenus.length > 0) {\n <hr class=\"tw:border-gray-300 tw:my-2\" />\n } @for (section of userMenus(); track section.label) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"section.items\"\n [label]=\"section.label\"\n (itemClick)=\"closeMobileMenu()\"\n ></eg-layout-simple-mobile-menu-group>\n\n @if (section.separator) {\n <hr class=\"tw:border-gray-300 tw:my-2\" />\n } }\n </div>\n }\n\n <!-- Main content -->\n <main [class]=\"_contentClass()\">\n @if (!loading()) {\n <div class=\"tw:flex tw:items-center tw:justify-center tw:h-full eg-layout-simple-main-content\">\n <ng-content />\n </div>\n }\n <div [class]=\"_contentBottomClass()\"></div>\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"_footerClass()\">\n <nav [class]=\"_computedFooterMenuClass()\">\n @for (item of footerMenus(); track item.label) { @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n } }\n </nav>\n\n <div class=\"tw:mt-2 tw:text-center\">{{ footerContent() }}</div>\n </footer>\n }\n</div>\n" }]
759
- }], ctorParameters: () => [{ type: i1$2.BreakpointObserver }], propDecorators: { sidebarEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarEnabled", required: false }] }], sidebarTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarTitle", required: false }] }], sidebarContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarContent", required: false }] }], sidebarToggleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarToggleLabel", required: false }] }], mobileMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMenuLabel", required: false }] }], userMenuTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "userMenuTrigger", required: false }] }], leftMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "leftMenus", required: false }] }], leftMenuGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "leftMenuGroups", required: false }] }], rightMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "rightMenus", required: false }] }], topMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "topMenus", required: false }] }], topSecondaryMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "topSecondaryMenus", required: false }] }], userMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "userMenus", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], logoLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoLink", required: false }] }], logoClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoClass", required: false }] }], headerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClass", required: false }] }], contentClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentClass", required: false }] }], contentBottomClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentBottomClass", required: false }] }], leftMenuClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "leftClass", required: false }] }], rightMenuClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rightClass", required: false }] }], topMenuClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "topClass", required: false }] }], leftLinkClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "leftLinkClass", required: false }] }], rightLinkClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rightLinkClass", required: false }] }], topLinkClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "topLinkClass", required: false }] }], searchEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], searchPlaceholderText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholderText", required: false }] }], searchEmptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEmptyText", required: false }] }], searchOptionTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchOptionTemplate", required: false }] }], searchLoaderFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLoaderFn", required: false }] }], searchTransformValueToSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTransformValueToSearch", required: false }] }], searchOptionChange: [{ type: i0.Output, args: ["searchOptionChange"] }], footerEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerEnabled", required: false }] }], footerMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerMenus", required: false }] }], footerMenuClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerMenuClass", required: false }] }], footerLinkClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerLinkClass", required: false }] }], footerContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerContent", required: false }] }], footerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerClass", required: false }] }], viewchildSheetRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EgLayoutSimpleSidebar), { isSignal: true }] }] } });
1220
+ EgLayoutSearch,
1221
+ EgLayoutNavigationItem,
1222
+ EgLayoutFlyoutNavbar,
1223
+ HlmDropdownMenu,
1224
+ HlmDropdownMenuItem,
1225
+ HlmDropdownMenuTrigger,
1226
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'tw:block tw:min-w-0' }, template: "@if (sidebarEnabled()) {\n<eg-layout-simple-sidebar\n [panelId]=\"sidebarId\"\n [title]=\"sidebarTitle()\"\n [content]=\"sidebarContent()\"\n [contentContext]=\"sidebarContext\"\n/>\n}\n\n<div\n [class]=\"hlm('tw:relative tw:isolate tw:flex tw:min-w-0 tw:flex-col tw:bg-background tw:text-foreground', fullHeight() && 'tw:min-h-dvh')\"\n>\n <a\n [href]=\"'#' + mainId\"\n (click)=\"focusContent($event)\"\n class=\"tw:sr-only tw:focus:not-sr-only tw:focus:absolute tw:focus:left-4 tw:focus:top-2 tw:focus:z-50 tw:focus:rounded-lg tw:focus:bg-background tw:focus:px-4 tw:focus:py-3 tw:focus:text-foreground tw:focus:outline-2 tw:focus:outline-ring\"\n >{{ skipLinkText() }}</a\n >\n\n <header [class]=\"headerClasses()\">\n <div class=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:gap-3 tw:md:flex-none tw:md:flex-wrap\">\n @if (sidebarEnabled()) {\n <button\n type=\"button\"\n [class]=\"iconButtonClasses\"\n [attr.aria-label]=\"sidebarToggleLabel()\"\n [attr.aria-expanded]=\"sidebarOpen()\"\n [attr.aria-controls]=\"sidebarId\"\n (click)=\"openSidebar()\"\n >\n <ng-icon [svg]=\"sidebarIcon\" size=\"20px\" aria-hidden=\"true\" />\n </button>\n }\n <a\n [routerLink]=\"logoLink()\"\n [attr.aria-label]=\"brandName() + ' home'\"\n class=\"tw:flex tw:min-h-11 tw:min-w-0 tw:items-center tw:gap-2.5 tw:rounded-lg tw:pr-2 tw:text-foreground tw:no-underline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring\"\n >\n @if (logo()) { <img [src]=\"logo()\" alt=\"\" [class]=\"logoClasses()\" /> }\n <span class=\"tw:truncate tw:text-base tw:font-semibold tw:tracking-tight\">{{ brandName() }}</span>\n </a>\n <nav aria-label=\"Primary navigation\" [class]=\"primaryNavigationClasses()\">\n @for (item of primaryNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n } @for (group of navigationGroups(); track $index) {\n <button\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"groupMenu\"\n class=\"tw:flex tw:min-h-11 tw:items-center tw:gap-2 tw:rounded-lg tw:px-3 tw:text-sm tw:font-medium tw:cursor-pointer tw:hover:bg-foreground/5 tw:focus-visible:outline-2 tw:focus-visible:outline-ring\"\n >\n {{ group.label || 'More' }} <ng-icon [svg]=\"chevronIcon\" size=\"14px\" aria-hidden=\"true\" />\n </button>\n <ng-template #groupMenu>\n <div hlmDropdownMenu class=\"tw:w-60\">\n @for (item of group.items; track $index) { @if (item.link && !item.disabled) {\n <a\n hlmDropdownMenuItem\n [routerLink]=\"item.link\"\n routerLinkActive=\"tw:bg-foreground/10 tw:font-semibold\"\n [routerLinkActiveOptions]=\"navigationMatchOptions(item)\"\n ariaCurrentWhenActive=\"page\"\n [class]=\"hlm('tw:min-h-11 tw:gap-2 tw:no-underline', item.class)\"\n >\n @if (item.icon) { <ng-icon [svg]=\"item.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n hlmDropdownMenuItem\n [disabled]=\"item.disabled || !item.action\"\n [class]=\"hlm('tw:min-h-11 tw:gap-2', item.class)\"\n (click)=\"item.action?.()\"\n >\n @if (item.icon) { <ng-icon [svg]=\"item.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ item.label }}\n </button>\n } }\n </div>\n </ng-template>\n }\n </nav>\n </div>\n\n <div class=\"tw:hidden tw:md:flex tw:flex-wrap tw:items-center tw:gap-3\">\n @if (searchEnabled() && !isMobile()) { <ng-container [ngTemplateOutlet]=\"searchTemplate\" /> } @if\n (utilityNavigation().length) {\n <nav aria-label=\"Utility navigation\" [class]=\"utilityNavigationClasses()\">\n @for (item of utilityNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n }\n </nav>\n } @if (userMenuSections().length) {\n <eg-layout-simple-user-menu\n [sections]=\"userMenuSections()\"\n [triggerTemplate]=\"userMenuTrigger()\"\n [triggerLabel]=\"userMenuLabel()\"\n />\n }\n </div>\n\n <button\n #mobileMenuTrigger\n type=\"button\"\n (click)=\"toggleMobileMenu()\"\n [class]=\"hlm(iconButtonClasses, 'tw:md:hidden')\"\n [attr.aria-label]=\"mobileMenuOpen() ? mobileMenuCloseLabel() : mobileMenuLabel()\"\n [attr.aria-expanded]=\"mobileMenuOpen()\"\n [attr.aria-controls]=\"mobileMenuId\"\n >\n <ng-icon [svg]=\"mobileMenuOpen() ? closeIcon : menuIcon\" size=\"20px\" aria-hidden=\"true\" />\n </button>\n </header>\n\n @if (sectionNavigation().length) {\n <nav aria-label=\"Section navigation\" [class]=\"sectionNavigationClasses()\">\n @for (item of sectionNavigation(); track $index) {\n <eg-layout-navigation-item [item]=\"item\" [itemClass]=\"navigationItemClass()\" />\n }\n </nav>\n } @if (flyoutNavigationGroups().length && !isMobile()) {\n <eg-layout-flyout-navbar\n class=\"tw:hidden tw:md:block\"\n [groups]=\"flyoutNavigationGroups()\"\n [label]=\"flyoutNavigationLabel()\"\n [closeLabel]=\"flyoutCloseLabel()\"\n [navbarClass]=\"flyoutNavigationClass()\"\n [panelClass]=\"flyoutPanelClass()\"\n [itemClass]=\"navigationItemClass()\"\n />\n } @if (secondaryNavigationGroups().length) {\n <nav aria-label=\"Secondary navigation\" [class]=\"secondaryNavigationClasses()\" tabindex=\"0\">\n @for (group of secondaryNavigationGroups(); track $index; let first = $first) {\n <div\n [class]=\"hlm('tw:flex tw:shrink-0 tw:items-center tw:gap-1', !first && 'tw:border-l tw:border-border tw:pl-5')\"\n >\n @if (group.label) {\n <span class=\"tw:mr-2 tw:text-xs tw:font-semibold tw:text-foreground/75 tw:whitespace-nowrap\"\n >{{ group.label }}</span\n >\n } @for (item of group.items; track $index) {\n <eg-layout-navigation-item\n [item]=\"item\"\n [itemClass]=\"hlm('tw:rounded-full tw:whitespace-nowrap', navigationItemClass())\"\n />\n }\n </div>\n }\n </nav>\n } @if (isMobile() && mobileMenuOpen()) {\n <nav\n [id]=\"mobileMenuId\"\n aria-label=\"Mobile navigation\"\n (keydown.escape)=\"closeMobileMenu(true); $event.stopPropagation()\"\n class=\"tw:md:hidden tw:max-h-[70dvh] tw:overflow-y-auto tw:overscroll-contain tw:space-y-4 tw:border-b tw:border-border tw:bg-background tw:p-4\"\n >\n @if (searchEnabled()) { <ng-container [ngTemplateOutlet]=\"searchTemplate\" /> }\n <eg-layout-simple-mobile-menu-group [items]=\"primaryNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @for (group of navigationGroups(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n <eg-layout-simple-mobile-menu-group [items]=\"sectionNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @for (group of flyoutNavigationGroups(); track $index) {\n <details class=\"tw:group/flyout tw:rounded-xl tw:border tw:border-border tw:bg-foreground/3\">\n <summary\n class=\"tw:flex tw:min-h-11 tw:list-none tw:items-center tw:justify-between tw:gap-2 tw:rounded-xl tw:px-3 tw:py-3 tw:text-sm tw:font-semibold tw:cursor-pointer tw:focus-visible:outline-2 tw:focus-visible:outline-ring tw:[&::-webkit-details-marker]:hidden\"\n >\n <span class=\"tw:flex tw:items-center tw:gap-2\">\n @if (group.icon) { <ng-icon [svg]=\"group.icon\" size=\"1rem\" aria-hidden=\"true\" /> } {{ group.label }}\n </span>\n <ng-icon\n [svg]=\"chevronIcon\"\n size=\"14px\"\n aria-hidden=\"true\"\n class=\"tw:shrink-0 tw:group-open/flyout:rotate-180\"\n />\n </summary>\n <div class=\"tw:space-y-2 tw:border-t tw:border-border tw:p-2\">\n @if (group.description) {\n <p class=\"tw:px-3 tw:py-2 tw:text-sm tw:text-foreground/75\">{{ group.description }}</p>\n } @for (item of group.items; track $index) {\n <eg-layout-navigation-item\n [item]=\"item\"\n appearance=\"card\"\n [itemClass]=\"navigationItemClass()\"\n (selected)=\"closeMobileMenu(true)\"\n />\n }\n </div>\n </details>\n } @for (group of secondaryNavigationGroups(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"group.items\"\n [label]=\"group.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n <eg-layout-simple-mobile-menu-group [items]=\"utilityNavigation()\" (itemSelected)=\"closeMobileMenu(true)\" />\n @if (userMenuSections().length) {\n <div class=\"tw:space-y-4 tw:border-t tw:border-border tw:pt-4\">\n @for (section of userMenuSections(); track $index) {\n <eg-layout-simple-mobile-menu-group\n [items]=\"section.items\"\n [label]=\"section.label\"\n (itemSelected)=\"closeMobileMenu(true)\"\n />\n }\n </div>\n }\n </nav>\n }\n\n <main #mainContent [id]=\"mainId\" tabindex=\"-1\" [attr.aria-busy]=\"loading()\" [class]=\"contentClasses()\">\n @if (loading()) {\n <div\n role=\"status\"\n class=\"tw:flex tw:min-h-48 tw:flex-1 tw:items-center tw:justify-center tw:gap-3 tw:text-sm tw:text-foreground/75\"\n >\n <span\n aria-hidden=\"true\"\n class=\"tw:size-5 tw:rounded-full tw:border-2 tw:border-border tw:border-t-foreground tw:motion-safe:animate-spin\"\n ></span>\n {{ loadingText() }}\n </div>\n }\n <div\n [hidden]=\"loading()\"\n [style.display]=\"loading() ? 'none' : null\"\n class=\"tw:w-full tw:min-w-0 eg-layout-simple-main-content\"\n >\n <ng-content />\n </div>\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"footerClasses()\">\n @if (footerText()) {\n <p>{{ footerText() }}</p>\n } @if (footerNavigation().length) {\n <nav aria-label=\"Footer navigation\" class=\"tw:flex tw:flex-wrap tw:items-center tw:gap-1\">\n @for (item of footerNavigation(); track $index) { <eg-layout-navigation-item [item]=\"item\" /> }\n </nav>\n }\n </footer>\n }\n</div>\n\n<ng-template #searchTemplate>\n <eg-layout-search\n [loader]=\"searchLoader()\"\n [resultLabel]=\"searchResultLabel()\"\n [placeholder]=\"searchPlaceholder()\"\n [emptyText]=\"searchEmptyText()\"\n [errorText]=\"searchErrorText()\"\n [resultTemplate]=\"searchResultTemplate()\"\n (resultSelected)=\"selectSearchResult($event)\"\n />\n</ng-template>\n" }]
1227
+ }], ctorParameters: () => [], propDecorators: { mobileMenuTrigger: [{ type: i0.ViewChild, args: ['mobileMenuTrigger', { isSignal: true }] }], mainContent: [{ type: i0.ViewChild, args: ['mainContent', { isSignal: true }] }], sidebar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EgLayoutSimpleSidebar), { isSignal: true }] }], sidebarEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarEnabled", required: false }] }], sidebarTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarTitle", required: false }] }], sidebarContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarContent", required: false }] }], sidebarToggleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarToggleLabel", required: false }] }], mobileMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMenuLabel", required: false }] }], mobileMenuCloseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMenuCloseLabel", required: false }] }], userMenuTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "userMenuTrigger", required: false }] }], userMenuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "userMenuLabel", required: false }] }], primaryNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "primaryNavigation", required: false }] }], navigationGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationGroups", required: false }] }], utilityNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "utilityNavigation", required: false }] }], sectionNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionNavigation", required: false }] }], secondaryNavigationGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryNavigationGroups", required: false }] }], flyoutNavigationGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "flyoutNavigationGroups", required: false }] }], flyoutNavigationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "flyoutNavigationLabel", required: false }] }], flyoutCloseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "flyoutCloseLabel", required: false }] }], userMenuSections: [{ type: i0.Input, args: [{ isSignal: true, alias: "userMenuSections", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], brandName: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandName", required: false }] }], logoLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoLink", required: false }] }], logoClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoClass", required: false }] }], fullHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullHeight", required: false }] }], headerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClass", required: false }] }], contentClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentClass", required: false }] }], primaryNavigationClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "primaryNavigationClass", required: false }] }], utilityNavigationClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "utilityNavigationClass", required: false }] }], sectionNavigationClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionNavigationClass", required: false }] }], secondaryNavigationClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryNavigationClass", required: false }] }], flyoutNavigationClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "flyoutNavigationClass", required: false }] }], flyoutPanelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "flyoutPanelClass", required: false }] }], navigationItemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationItemClass", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], skipLinkText: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLinkText", required: false }] }], searchEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEnabled", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], searchEmptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchEmptyText", required: false }] }], searchErrorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchErrorText", required: false }] }], searchResultTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchResultTemplate", required: false }] }], searchLoader: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLoader", required: false }] }], searchResultLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchResultLabel", required: false }] }], searchResultSelected: [{ type: i0.Output, args: ["searchResultSelected"] }], footerEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerEnabled", required: false }] }], footerNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerNavigation", required: false }] }], footerText: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerText", required: false }] }], footerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerClass", required: false }] }] } });
760
1228
 
761
1229
  /*
762
1230
  * Public API Surface of layout-simple
@@ -766,5 +1234,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
766
1234
  * Generated bundle index. Do not edit.
767
1235
  */
768
1236
 
769
- export { EG_LAYOUT_SIMPLE_MOBILE_BREAKPOINT, EgGenericAutocomplete, EgLayoutSimple, EgLayoutSimpleUserMenu };
1237
+ export { EG_LAYOUT_SIMPLE_MOBILE_BREAKPOINT, EgLayoutSearch, EgLayoutSimple, EgLayoutSimpleUserMenu };
770
1238