structra-ui 0.2.54 → 0.2.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import '../structra-ui.css';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, booleanAttribute, Input, HostBinding, ChangeDetectionStrategy, Component, ElementRef, ViewChild, inject, ChangeDetectorRef, Injector, DestroyRef, EventEmitter, Output, Directive, numberAttribute, computed, Injectable, input, output, HostListener, ViewChildren, forwardRef, ApplicationRef, afterNextRender, ContentChildren, NgZone, Renderer2, effect, TemplateRef, ContentChild } from '@angular/core';
3
+ import { signal, booleanAttribute, Input, HostBinding, ChangeDetectionStrategy, Component, ElementRef, ViewChild, inject, ChangeDetectorRef, Injector, DestroyRef, EventEmitter, Output, Directive, numberAttribute, computed, Injectable, input, output, afterNextRender, HostListener, ViewChildren, forwardRef, ApplicationRef, ContentChildren, NgZone, Renderer2, effect, TemplateRef, ContentChild } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@angular/forms';
6
6
  import { Validators, FormGroupDirective, NgForm, NgControl, NG_VALUE_ACCESSOR, FormsModule, FormGroup, FormArray, FormControl } from '@angular/forms';
@@ -1186,6 +1186,19 @@ function buildMenuRows(nodes) {
1186
1186
  }
1187
1187
  return rows;
1188
1188
  }
1189
+ /**
1190
+ * Compara ids de itens do menu (rotas, chaves de navegação).
1191
+ * Evita falhas quando o modelo usa `string` e o estado activo vem como `number` (ou o contrário).
1192
+ */
1193
+ function menuItemIdsEqual(a, b) {
1194
+ if (Object.is(a, b)) {
1195
+ return true;
1196
+ }
1197
+ if (a == null || b == null) {
1198
+ return false;
1199
+ }
1200
+ return String(a) === String(b);
1201
+ }
1189
1202
  function focusableActionCount(rows) {
1190
1203
  return rows.filter((r) => (r.kind === 'action' || r.kind === 'submenu') && r.focusIndex !== null).length;
1191
1204
  }
@@ -1199,7 +1212,7 @@ function menuNodeTreeContainsId(items, selectedId) {
1199
1212
  continue;
1200
1213
  }
1201
1214
  if (node.kind === 'item') {
1202
- if (node.id === selectedId) {
1215
+ if (menuItemIdsEqual(node.id, selectedId)) {
1203
1216
  return true;
1204
1217
  }
1205
1218
  }
@@ -1233,7 +1246,7 @@ function collectGroupIdsContainingSelectedItem(nodes, selectedId) {
1233
1246
  }
1234
1247
  }
1235
1248
  else if (n.kind === 'item') {
1236
- if (n.id === selectedId) {
1249
+ if (menuItemIdsEqual(n.id, selectedId)) {
1237
1250
  hit = true;
1238
1251
  }
1239
1252
  }
@@ -1342,8 +1355,17 @@ function purgeMenuGroupExpansionStorageAfterReload() {
1342
1355
  }
1343
1356
  class MenuListBodyComponent {
1344
1357
  constructor(cdr, hostRef) {
1358
+ this.destroyRef = inject(DestroyRef);
1359
+ this.injector = inject(Injector);
1345
1360
  /** Igual a `[appTheme]` na lib; omitir = tema global (ex.: propagado por `app-sidebar`). */
1346
1361
  this.appTheme = input(...(ngDevMode ? [undefined, { debugName: "appTheme" }] : /* istanbul ignore next */ []));
1362
+ /**
1363
+ * Emitido após sincronizar expansão de grupos / submenu com `selectedItemId` no próximo render.
1364
+ * A sidebar usa isto para voltar a correr o scroll até ao `--selected` (ex.: drawer mobile `@if (open)`).
1365
+ */
1366
+ this.selectionScrollHint = output();
1367
+ /** Invalida callbacks `afterNextRender` pendentes do hint de scroll. */
1368
+ this.selectionLayoutHintGen = 0;
1347
1369
  this.items = [];
1348
1370
  /** Prefixo dos `id` das opções focáveis (`${menuId}-opt-${focusIndex}`). */
1349
1371
  this.menuId = 'app-menu';
@@ -1411,6 +1433,12 @@ class MenuListBodyComponent {
1411
1433
  this.cdr = cdr;
1412
1434
  this.hostRef = hostRef;
1413
1435
  this.effectiveThemeId = injectEffectiveThemeId(this.appTheme);
1436
+ this.destroyRef.onDestroy(() => {
1437
+ this.selectionLayoutHintGen++;
1438
+ });
1439
+ }
1440
+ ngAfterViewInit() {
1441
+ this.scheduleSelectionLayoutHintAfterRender();
1414
1442
  }
1415
1443
  overlayPanelClasses() {
1416
1444
  return [...getThemeClassList(this.effectiveThemeId()), 'menu-submenu__cdk-panel'];
@@ -1459,18 +1487,13 @@ class MenuListBodyComponent {
1459
1487
  this.activeIndex = this.focusableCount - 1;
1460
1488
  }
1461
1489
  }
1462
- else if (changes['selectedItemId'] &&
1463
- !changes['items'] &&
1464
- !changes['expandAllGroupsInitially']) {
1465
- if (this.ensureExpandedGroupsForSelection()) {
1466
- this.syncDisplayRows();
1467
- if (this.focusableCount === 0) {
1468
- this.activeIndex = -1;
1469
- }
1470
- else if (this.activeIndex >= this.focusableCount) {
1471
- this.activeIndex = this.focusableCount - 1;
1472
- }
1473
- }
1490
+ /**
1491
+ * Fim da cadeia `if / else if`: mudanças só em `selectedItemId` já não tinham ramo próprio e,
1492
+ * em alguns ciclos, `selectedItemId` combinava com `groupCollapsible` / outros — o ramo errado
1493
+ * impedia `ensureExpandedGroupsForSelection`. Reconciliar sempre que o caminho da selecção importa.
1494
+ */
1495
+ if (this.shouldReconcileSelectionPath(changes)) {
1496
+ this.reconcileSelectionPathSync();
1474
1497
  }
1475
1498
  if (changes['selectedItemId'] ||
1476
1499
  changes['items'] ||
@@ -1484,6 +1507,71 @@ class MenuListBodyComponent {
1484
1507
  changes['persistGroupExpansion']) {
1485
1508
  this.cdr.markForCheck();
1486
1509
  }
1510
+ if (this.shouldScheduleSelectionScrollHint(changes)) {
1511
+ this.scheduleSelectionLayoutHintAfterRender();
1512
+ }
1513
+ }
1514
+ shouldReconcileSelectionPath(changes) {
1515
+ return !!(changes['selectedItemId'] ||
1516
+ changes['items'] ||
1517
+ changes['expandAllGroupsInitially'] ||
1518
+ changes['compressText'] ||
1519
+ changes['groupCollapsible'] ||
1520
+ changes['groupDefaultExpansion'] ||
1521
+ changes['persistGroupExpansion'] ||
1522
+ changes['clickToOpen']);
1523
+ }
1524
+ shouldScheduleSelectionScrollHint(changes) {
1525
+ return this.shouldReconcileSelectionPath(changes);
1526
+ }
1527
+ /**
1528
+ * Garante expansão + submenu para a rota activa depois do {@link MenuListComponent} ter referência
1529
+ * ao `ViewChild` (caso típico do drawer mobile).
1530
+ */
1531
+ syncRouteSelectionExpansion() {
1532
+ if ((this.items?.length ?? 0) > 0 && !this.rows.length) {
1533
+ this.rebuildRowsFromItems();
1534
+ this.selectionScrollHint.emit();
1535
+ return;
1536
+ }
1537
+ this.reconcileSelectionPathSync();
1538
+ this.selectionScrollHint.emit();
1539
+ }
1540
+ /** Abre grupos no caminho da rota activa e submenu em modo clique — síncrono após inputs. */
1541
+ reconcileSelectionPathSync() {
1542
+ if (!this.rows.length) {
1543
+ if ((this.items?.length ?? 0) > 0) {
1544
+ this.rebuildRowsFromItems();
1545
+ }
1546
+ return;
1547
+ }
1548
+ let touched = false;
1549
+ if (this.ensureExpandedGroupsForSelection()) {
1550
+ this.syncDisplayRows();
1551
+ touched = true;
1552
+ }
1553
+ if (this.ensureSubmenuOpenForSelection()) {
1554
+ touched = true;
1555
+ }
1556
+ if (touched) {
1557
+ if (this.focusableCount === 0) {
1558
+ this.activeIndex = -1;
1559
+ }
1560
+ else if (this.activeIndex >= this.focusableCount) {
1561
+ this.activeIndex = this.focusableCount - 1;
1562
+ }
1563
+ this.cdr.markForCheck();
1564
+ }
1565
+ }
1566
+ scheduleSelectionLayoutHintAfterRender() {
1567
+ const gen = ++this.selectionLayoutHintGen;
1568
+ afterNextRender(() => {
1569
+ if (gen !== this.selectionLayoutHintGen) {
1570
+ return;
1571
+ }
1572
+ this.reconcileSelectionPathSync();
1573
+ this.selectionScrollHint.emit();
1574
+ }, { injector: this.injector });
1487
1575
  }
1488
1576
  getRowsSourceItems() {
1489
1577
  return [...(this.items ?? [])];
@@ -1505,6 +1593,7 @@ class MenuListBodyComponent {
1505
1593
  this.activeIndex = -1;
1506
1594
  }
1507
1595
  this.applySearchSubmenuAutoOpen();
1596
+ this.ensureSubmenuOpenForSelection();
1508
1597
  }
1509
1598
  /**
1510
1599
  * Com pesquisa activa (lista filtrada), abre o primeiro submenu deste nível que
@@ -1626,13 +1715,11 @@ class MenuListBodyComponent {
1626
1715
  }
1627
1716
  /**
1628
1717
  * Abre todos os grupos no caminho até ao item com `selectedItemId` (árvore alinhada a {@link buildMenuRows}).
1629
- * Usado ao expandir a sidebar do rail e quando a selecção muda — permite depois o scroll até ao `--selected`.
1718
+ * Corre também com `compressText` activo para `expandedGroupIds` ficar correcto quando o rail termina;
1719
+ * com texto comprimido, {@link isGroupExpanded} continua a mostrar todas as linhas na lista.
1630
1720
  */
1631
1721
  ensureExpandedGroupsForSelection() {
1632
- if (this.selectedItemId == null ||
1633
- !this.groupCollapsible ||
1634
- this.compressText ||
1635
- this.expandAllGroupsInitially) {
1722
+ if (this.selectedItemId == null || !this.groupCollapsible) {
1636
1723
  return false;
1637
1724
  }
1638
1725
  const gids = collectGroupIdsContainingSelectedItem(this.getRowsSourceItems(), this.selectedItemId);
@@ -1652,6 +1739,45 @@ class MenuListBodyComponent {
1652
1739
  }
1653
1740
  return changed;
1654
1741
  }
1742
+ /**
1743
+ * Com `clickToOpen`, após remount ou mudança de `selectedItemId`, abre o submenu que contém a folha activa
1744
+ * para o realce ficar visível. Em modo rail (`compressText`) os grupos parecem sempre abertos, mas
1745
+ * `expandedGroupIds` ainda precisa do caminho para quando o texto deixa de estar comprimido.
1746
+ * Fecha o painel se a selecção já não estiver sob nenhum submenu deste nível.
1747
+ */
1748
+ ensureSubmenuOpenForSelection() {
1749
+ if (!this.clickToOpen) {
1750
+ return false;
1751
+ }
1752
+ if (this.selectedItemId == null) {
1753
+ if (this.openSubmenuKey !== null) {
1754
+ this.openSubmenuKey = null;
1755
+ return true;
1756
+ }
1757
+ return false;
1758
+ }
1759
+ for (let i = 0; i < this.displayRows.length; i++) {
1760
+ const row = this.displayRows[i];
1761
+ if (row.kind !== 'submenu' || row.item.disabled) {
1762
+ continue;
1763
+ }
1764
+ if (!menuNodeTreeContainsId(row.item.items, this.selectedItemId)) {
1765
+ continue;
1766
+ }
1767
+ const key = this.submenuRowKey(row, i);
1768
+ if (this.openSubmenuKey === key) {
1769
+ return false;
1770
+ }
1771
+ this.openSubmenuKey = key;
1772
+ this.queueFocusNestedFirst();
1773
+ return true;
1774
+ }
1775
+ if (this.openSubmenuKey !== null) {
1776
+ this.openSubmenuKey = null;
1777
+ return true;
1778
+ }
1779
+ return false;
1780
+ }
1655
1781
  syncDisplayRows() {
1656
1782
  const visible = this.rows.filter((r) => this.isRowVisible(r));
1657
1783
  let fi = 0;
@@ -1907,10 +2033,10 @@ class MenuListBodyComponent {
1907
2033
  return false;
1908
2034
  }
1909
2035
  if (row.kind === 'action') {
1910
- return row.item.id === this.selectedItemId;
2036
+ return menuItemIdsEqual(row.item.id, this.selectedItemId);
1911
2037
  }
1912
2038
  if (row.kind === 'submenu') {
1913
- return (row.item.id === this.selectedItemId ||
2039
+ return (menuItemIdsEqual(row.item.id, this.selectedItemId) ||
1914
2040
  menuNodeTreeContainsId(row.item.items, this.selectedItemId));
1915
2041
  }
1916
2042
  return false;
@@ -2065,7 +2191,7 @@ class MenuListBodyComponent {
2065
2191
  }
2066
2192
  }
2067
2193
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuListBodyComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
2068
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuListBodyComponent, isStandalone: true, selector: "app-menu-list-body", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, nested: { classPropertyName: "nested", publicName: "nested", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, compressText: { classPropertyName: "compressText", publicName: "compressText", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null }, persistGroupExpansion: { classPropertyName: "persistGroupExpansion", publicName: "persistGroupExpansion", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, expandAllGroupsInitially: { classPropertyName: "expandAllGroupsInitially", publicName: "expandAllGroupsInitially", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, outputs: { itemSelect: "itemSelect", closeRequest: "closeRequest", submenuBack: "submenuBack", groupToggled: "groupToggled" }, host: { listeners: { "focusin": "onFocusIn($event)", "keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "nestedLists", predicate: MenuListBodyComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"menu-list\" [class.menu-list--nested]=\"nested\" [class.menu-list--dense]=\"dense\"\n [class.menu-list--compress-text]=\"compressText\" tabindex=\"-1\" (mouseleave)=\"onMenuSurfaceLeave()\">\n <div class=\"menu-list__toolbar\">\n <ng-content />\n </div>\n <div class=\"menu-list__viewport\" cdkScrollable tabindex=\"-1\">\n <div class=\"menu-list__items\" role=\"menu\" [attr.aria-labelledby]=\"null\" tabindex=\"-1\">\n @for (row of displayRows; track trackDisplayRow($index, row); let idx = $index) {\n @switch (row.kind) {\n @case ('divider') {\n <app-menu-divider (mouseenter)=\"onNonOptionSurfaceEnter()\" />\n }\n @case ('group') {\n <div class=\"menu-list__group-row\" [class.menu-list__group-row--pinned]=\"row.alwaysExpanded\"\n [attr.data-structra-group-id]=\"row.groupId\" (mouseenter)=\"onNonOptionSurfaceEnter()\">\n <app-menu-group [label]=\"row.label\" [hideLabel]=\"compressText\"\n [collapsible]=\"groupCollapsible && !compressText && !row.alwaysExpanded\"\n [expanded]=\"isGroupExpanded(row.groupId)\" (toggleExpand)=\"toggleGroup(row.groupId)\" />\n </div>\n }\n @case ('submenu') {\n <div class=\"menu-list__submenu-wrap\" cdkOverlayOrigin #subOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onSubmenuTriggerEnter(row, idx)\" (mouseleave)=\"onSubmenuTriggerLeave(row, idx)\">\n <div class=\"menu-list__option menu-list__option--submenu\" role=\"menuitem\" [attr.aria-haspopup]=\"'true'\"\n [attr.aria-expanded]=\"isSubmenuOpen(row, idx)\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.title]=\"compressText ? row.item.label : null\"\n [attr.aria-label]=\"compressText ? row.item.label : null\" [class.menu-list__option--disabled]=\"row.item.disabled\"\n [class.menu-list__option--active]=\"isActiveRow(row)\" [class.menu-list__option--selected]=\"isRowSelected(row)\"\n (click)=\"onSubmenuRowClick($event, row, idx)\" (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n <span class=\"menu-list__submenu-chevron\" aria-hidden=\"true\">\n @if (isSubmenuOpen(row, idx)) {\n <i class=\"fa-solid fa-chevron-right\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </span>\n </div>\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"subOrigin\"\n [cdkConnectedOverlayOpen]=\"isSubmenuOpen(row, idx)\" [cdkConnectedOverlayPositions]=\"submenuPositions\"\n [cdkConnectedOverlayPush]=\"true\" [cdkConnectedOverlayPanelClass]=\"overlayPanelClasses()\"\n [cdkConnectedOverlayMinWidth]=\"200\" (overlayOutsideClick)=\"onSubmenuOutsideClick(row, idx)\">\n <div class=\"menu-submenu__panel\" [ngClass]=\"panelThemeNgClass()\" (mouseenter)=\"onSubmenuPanelEnter()\"\n (mouseleave)=\"onSubmenuPanelLeave(row, idx)\" (click)=\"$event.stopPropagation()\">\n <app-menu-list-body [items]=\"row.item.items\" [menuId]=\"submenuMenuId(row)\" [nested]=\"true\" [dense]=\"dense\"\n [compressText]=\"compressText\" [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\" [persistGroupExpansion]=\"persistGroupExpansion\"\n [expandAllGroupsInitially]=\"expandAllGroupsInitially\"\n [clickToOpen]=\"clickToOpen\" [selectedItemId]=\"selectedItemId\" [appTheme]=\"appTheme()\"\n (itemSelect)=\"onNestedItemSelect($event)\" (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"closeOpenSubmenu()\" />\n </div>\n </ng-template>\n </div>\n }\n @case ('action') {\n <div class=\"menu-list__option\" role=\"menuitem\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.aria-busy]=\"row.item.loading ? true : null\"\n [attr.title]=\"compressText ? row.item.label : null\" [attr.aria-label]=\"compressText ? row.item.label : null\"\n [class.menu-list__option--disabled]=\"row.item.disabled\" [class.menu-list__option--loading]=\"row.item.loading\"\n [class.menu-list__option--danger]=\"row.item.danger\" [class.menu-list__option--active]=\"isActiveRow(row)\"\n [class.menu-list__option--selected]=\"isRowSelected(row)\" (click)=\"onItemClick($event, row.item)\"\n (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.loading) {\n <span class=\"menu-list__icon menu-list__icon--spin\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-spinner\"></i>\n </span>\n } @else if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n </div>\n }\n }\n }\n </div>\n </div>\n</div>", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => MenuListBodyComponent), selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled"] }, { kind: "directive", type: i0.forwardRef(() => NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => CdkConnectedOverlay), selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i0.forwardRef(() => CdkOverlayOrigin), selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i0.forwardRef(() => CdkScrollable), selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: i0.forwardRef(() => MenuDividerComponent), selector: "app-menu-divider" }, { kind: "component", type: i0.forwardRef(() => MenuGroupComponent), selector: "app-menu-group", inputs: ["label", "hideLabel", "collapsible", "expanded"], outputs: ["toggleExpand"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2194
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuListBodyComponent, isStandalone: true, selector: "app-menu-list-body", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, nested: { classPropertyName: "nested", publicName: "nested", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, compressText: { classPropertyName: "compressText", publicName: "compressText", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null }, persistGroupExpansion: { classPropertyName: "persistGroupExpansion", publicName: "persistGroupExpansion", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, expandAllGroupsInitially: { classPropertyName: "expandAllGroupsInitially", publicName: "expandAllGroupsInitially", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, outputs: { selectionScrollHint: "selectionScrollHint", itemSelect: "itemSelect", closeRequest: "closeRequest", submenuBack: "submenuBack", groupToggled: "groupToggled" }, host: { listeners: { "focusin": "onFocusIn($event)", "keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "nestedLists", predicate: MenuListBodyComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"menu-list\" [class.menu-list--nested]=\"nested\" [class.menu-list--dense]=\"dense\"\n [class.menu-list--compress-text]=\"compressText\" tabindex=\"-1\" (mouseleave)=\"onMenuSurfaceLeave()\">\n <div class=\"menu-list__toolbar\">\n <ng-content />\n </div>\n <div class=\"menu-list__viewport\" cdkScrollable tabindex=\"-1\">\n <div class=\"menu-list__items\" role=\"menu\" [attr.aria-labelledby]=\"null\" tabindex=\"-1\">\n @for (row of displayRows; track trackDisplayRow($index, row); let idx = $index) {\n @switch (row.kind) {\n @case ('divider') {\n <app-menu-divider (mouseenter)=\"onNonOptionSurfaceEnter()\" />\n }\n @case ('group') {\n <div class=\"menu-list__group-row\" [class.menu-list__group-row--pinned]=\"row.alwaysExpanded\"\n [attr.data-structra-group-id]=\"row.groupId\" (mouseenter)=\"onNonOptionSurfaceEnter()\">\n <app-menu-group [label]=\"row.label\" [hideLabel]=\"compressText\"\n [collapsible]=\"groupCollapsible && !compressText && !row.alwaysExpanded\"\n [expanded]=\"isGroupExpanded(row.groupId)\" (toggleExpand)=\"toggleGroup(row.groupId)\" />\n </div>\n }\n @case ('submenu') {\n <div class=\"menu-list__submenu-wrap\" cdkOverlayOrigin #subOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onSubmenuTriggerEnter(row, idx)\" (mouseleave)=\"onSubmenuTriggerLeave(row, idx)\">\n <div class=\"menu-list__option menu-list__option--submenu\" role=\"menuitem\" [attr.aria-haspopup]=\"'true'\"\n [attr.aria-expanded]=\"isSubmenuOpen(row, idx)\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.title]=\"compressText ? row.item.label : null\"\n [attr.aria-label]=\"compressText ? row.item.label : null\" [class.menu-list__option--disabled]=\"row.item.disabled\"\n [class.menu-list__option--active]=\"isActiveRow(row)\" [class.menu-list__option--selected]=\"isRowSelected(row)\"\n (click)=\"onSubmenuRowClick($event, row, idx)\" (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n <span class=\"menu-list__submenu-chevron\" aria-hidden=\"true\">\n @if (isSubmenuOpen(row, idx)) {\n <i class=\"fa-solid fa-chevron-right\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </span>\n </div>\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"subOrigin\"\n [cdkConnectedOverlayOpen]=\"isSubmenuOpen(row, idx)\" [cdkConnectedOverlayPositions]=\"submenuPositions\"\n [cdkConnectedOverlayPush]=\"true\" [cdkConnectedOverlayPanelClass]=\"overlayPanelClasses()\"\n [cdkConnectedOverlayMinWidth]=\"200\" (overlayOutsideClick)=\"onSubmenuOutsideClick(row, idx)\">\n <div class=\"menu-submenu__panel\" [ngClass]=\"panelThemeNgClass()\" (mouseenter)=\"onSubmenuPanelEnter()\"\n (mouseleave)=\"onSubmenuPanelLeave(row, idx)\" (click)=\"$event.stopPropagation()\">\n <app-menu-list-body [items]=\"row.item.items\" [menuId]=\"submenuMenuId(row)\" [nested]=\"true\" [dense]=\"dense\"\n [compressText]=\"compressText\" [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\" [persistGroupExpansion]=\"persistGroupExpansion\"\n [expandAllGroupsInitially]=\"expandAllGroupsInitially\"\n [clickToOpen]=\"clickToOpen\" [selectedItemId]=\"selectedItemId\" [appTheme]=\"appTheme()\"\n (itemSelect)=\"onNestedItemSelect($event)\" (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"closeOpenSubmenu()\" />\n </div>\n </ng-template>\n </div>\n }\n @case ('action') {\n <div class=\"menu-list__option\" role=\"menuitem\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.aria-busy]=\"row.item.loading ? true : null\"\n [attr.title]=\"compressText ? row.item.label : null\" [attr.aria-label]=\"compressText ? row.item.label : null\"\n [class.menu-list__option--disabled]=\"row.item.disabled\" [class.menu-list__option--loading]=\"row.item.loading\"\n [class.menu-list__option--danger]=\"row.item.danger\" [class.menu-list__option--active]=\"isActiveRow(row)\"\n [class.menu-list__option--selected]=\"isRowSelected(row)\" (click)=\"onItemClick($event, row.item)\"\n (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.loading) {\n <span class=\"menu-list__icon menu-list__icon--spin\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-spinner\"></i>\n </span>\n } @else if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n </div>\n }\n }\n }\n </div>\n </div>\n</div>", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => MenuListBodyComponent), selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["selectionScrollHint", "itemSelect", "closeRequest", "submenuBack", "groupToggled"] }, { kind: "directive", type: i0.forwardRef(() => NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => CdkConnectedOverlay), selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i0.forwardRef(() => CdkOverlayOrigin), selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i0.forwardRef(() => CdkScrollable), selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: i0.forwardRef(() => MenuDividerComponent), selector: "app-menu-divider" }, { kind: "component", type: i0.forwardRef(() => MenuGroupComponent), selector: "app-menu-group", inputs: ["label", "hideLabel", "collapsible", "expanded"], outputs: ["toggleExpand"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2069
2195
  }
2070
2196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuListBodyComponent, decorators: [{
2071
2197
  type: Component,
@@ -2078,7 +2204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2078
2204
  MenuDividerComponent,
2079
2205
  MenuGroupComponent,
2080
2206
  ], template: "<div class=\"menu-list\" [class.menu-list--nested]=\"nested\" [class.menu-list--dense]=\"dense\"\n [class.menu-list--compress-text]=\"compressText\" tabindex=\"-1\" (mouseleave)=\"onMenuSurfaceLeave()\">\n <div class=\"menu-list__toolbar\">\n <ng-content />\n </div>\n <div class=\"menu-list__viewport\" cdkScrollable tabindex=\"-1\">\n <div class=\"menu-list__items\" role=\"menu\" [attr.aria-labelledby]=\"null\" tabindex=\"-1\">\n @for (row of displayRows; track trackDisplayRow($index, row); let idx = $index) {\n @switch (row.kind) {\n @case ('divider') {\n <app-menu-divider (mouseenter)=\"onNonOptionSurfaceEnter()\" />\n }\n @case ('group') {\n <div class=\"menu-list__group-row\" [class.menu-list__group-row--pinned]=\"row.alwaysExpanded\"\n [attr.data-structra-group-id]=\"row.groupId\" (mouseenter)=\"onNonOptionSurfaceEnter()\">\n <app-menu-group [label]=\"row.label\" [hideLabel]=\"compressText\"\n [collapsible]=\"groupCollapsible && !compressText && !row.alwaysExpanded\"\n [expanded]=\"isGroupExpanded(row.groupId)\" (toggleExpand)=\"toggleGroup(row.groupId)\" />\n </div>\n }\n @case ('submenu') {\n <div class=\"menu-list__submenu-wrap\" cdkOverlayOrigin #subOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onSubmenuTriggerEnter(row, idx)\" (mouseleave)=\"onSubmenuTriggerLeave(row, idx)\">\n <div class=\"menu-list__option menu-list__option--submenu\" role=\"menuitem\" [attr.aria-haspopup]=\"'true'\"\n [attr.aria-expanded]=\"isSubmenuOpen(row, idx)\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.title]=\"compressText ? row.item.label : null\"\n [attr.aria-label]=\"compressText ? row.item.label : null\" [class.menu-list__option--disabled]=\"row.item.disabled\"\n [class.menu-list__option--active]=\"isActiveRow(row)\" [class.menu-list__option--selected]=\"isRowSelected(row)\"\n (click)=\"onSubmenuRowClick($event, row, idx)\" (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n <span class=\"menu-list__submenu-chevron\" aria-hidden=\"true\">\n @if (isSubmenuOpen(row, idx)) {\n <i class=\"fa-solid fa-chevron-right\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </span>\n </div>\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"subOrigin\"\n [cdkConnectedOverlayOpen]=\"isSubmenuOpen(row, idx)\" [cdkConnectedOverlayPositions]=\"submenuPositions\"\n [cdkConnectedOverlayPush]=\"true\" [cdkConnectedOverlayPanelClass]=\"overlayPanelClasses()\"\n [cdkConnectedOverlayMinWidth]=\"200\" (overlayOutsideClick)=\"onSubmenuOutsideClick(row, idx)\">\n <div class=\"menu-submenu__panel\" [ngClass]=\"panelThemeNgClass()\" (mouseenter)=\"onSubmenuPanelEnter()\"\n (mouseleave)=\"onSubmenuPanelLeave(row, idx)\" (click)=\"$event.stopPropagation()\">\n <app-menu-list-body [items]=\"row.item.items\" [menuId]=\"submenuMenuId(row)\" [nested]=\"true\" [dense]=\"dense\"\n [compressText]=\"compressText\" [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\" [persistGroupExpansion]=\"persistGroupExpansion\"\n [expandAllGroupsInitially]=\"expandAllGroupsInitially\"\n [clickToOpen]=\"clickToOpen\" [selectedItemId]=\"selectedItemId\" [appTheme]=\"appTheme()\"\n (itemSelect)=\"onNestedItemSelect($event)\" (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"closeOpenSubmenu()\" />\n </div>\n </ng-template>\n </div>\n }\n @case ('action') {\n <div class=\"menu-list__option\" role=\"menuitem\" [id]=\"row.focusIndex !== null ? optionId(row.focusIndex) : null\"\n [attr.tabindex]=\"row.focusIndex !== null && !row.item.disabled ? (isActiveRow(row) ? 0 : -1) : -1\"\n [attr.aria-disabled]=\"row.item.disabled ? true : null\" [attr.aria-busy]=\"row.item.loading ? true : null\"\n [attr.title]=\"compressText ? row.item.label : null\" [attr.aria-label]=\"compressText ? row.item.label : null\"\n [class.menu-list__option--disabled]=\"row.item.disabled\" [class.menu-list__option--loading]=\"row.item.loading\"\n [class.menu-list__option--danger]=\"row.item.danger\" [class.menu-list__option--active]=\"isActiveRow(row)\"\n [class.menu-list__option--selected]=\"isRowSelected(row)\" (click)=\"onItemClick($event, row.item)\"\n (mouseenter)=\"onRowMouseEnter(row)\">\n @if (row.item.loading) {\n <span class=\"menu-list__icon menu-list__icon--spin\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-spinner\"></i>\n </span>\n } @else if (row.item.icon?.trim()) {\n <span class=\"menu-list__icon\" aria-hidden=\"true\">\n <i [ngClass]=\"row.item.icon\"></i>\n </span>\n }\n <span class=\"menu-list__text\">\n <span class=\"menu-list__label\">{{ row.item.label }}</span>\n @if (row.item.description?.trim()) {\n <span class=\"menu-list__description\">{{ row.item.description }}</span>\n }\n </span>\n </div>\n }\n }\n }\n </div>\n </div>\n</div>", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"] }]
2081
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { appTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTheme", required: false }] }], items: [{
2207
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { appTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTheme", required: false }] }], selectionScrollHint: [{ type: i0.Output, args: ["selectionScrollHint"] }], items: [{
2082
2208
  type: Input,
2083
2209
  args: [{ required: true }]
2084
2210
  }], menuId: [{
@@ -2188,7 +2314,7 @@ class DropdownMenuComponent {
2188
2314
  this.setOpen(false);
2189
2315
  }
2190
2316
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DropdownMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2191
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.9", type: DropdownMenuComponent, isStandalone: true, selector: "app-dropdown-menu", inputs: { items: "items", placement: "placement", minWidthPx: "minWidthPx", matchTriggerWidth: ["matchTriggerWidth", "matchTriggerWidth", booleanAttribute], menuId: "menuId" }, outputs: { itemSelect: "itemSelect", openChange: "openChange" }, viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, static: true }, { propertyName: "menuList", first: true, predicate: MenuListBodyComponent, descendants: true }], ngImport: i0, template: "<app-dropdown-base\r\n class=\"dropdown-menu\"\r\n [open]=\"open\"\r\n (openChange)=\"onBaseOpenChange($event)\"\r\n [panelTemplate]=\"panelTpl\"\r\n [panelWidthPx]=\"effectivePanelWidth\"\r\n [connectedPositions]=\"connectedPositions\"\r\n [pushConnectedOverlay]=\"true\"\r\n [hasBackdrop]=\"true\"\r\n [closeOnEscape]=\"true\"\r\n [bareOverlayPanel]=\"true\"\r\n>\r\n <span\r\n class=\"dropdown-menu__trigger-slot\"\r\n appDropdownTrigger\r\n (click)=\"onTriggerClick($event)\"\r\n [attr.aria-expanded]=\"open\"\r\n aria-haspopup=\"menu\"\r\n >\r\n <ng-content />\r\n </span>\r\n</app-dropdown-base>\r\n\r\n<ng-template #panelTpl>\r\n <div class=\"dropdown-menu__panel-inner\">\r\n <app-menu-list-body\r\n [items]=\"items\"\r\n [menuId]=\"resolvedMenuId\"\r\n [clickToOpen]=\"false\"\r\n (itemSelect)=\"onItemSelect($event)\"\r\n (closeRequest)=\"onCloseRequest()\"\r\n />\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:inline-block;max-width:100%;vertical-align:middle}.dropdown-menu{display:inline-flex;max-width:100%;min-width:0}.dropdown-menu__trigger-slot{display:inline-flex;max-width:100%;min-width:0;cursor:pointer}.dropdown-menu__panel-inner{box-sizing:border-box;min-width:0}\n"], dependencies: [{ kind: "component", type: DropdownBaseComponent, selector: "app-dropdown-base", inputs: ["open", "panelTemplate", "panelWidthPx", "closeOnEscape", "hasBackdrop", "connectedPositions", "pushConnectedOverlay", "scrollStrategy", "bareOverlayPanel"], outputs: ["openChange"] }, { kind: "component", type: MenuListBodyComponent, selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2317
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.9", type: DropdownMenuComponent, isStandalone: true, selector: "app-dropdown-menu", inputs: { items: "items", placement: "placement", minWidthPx: "minWidthPx", matchTriggerWidth: ["matchTriggerWidth", "matchTriggerWidth", booleanAttribute], menuId: "menuId" }, outputs: { itemSelect: "itemSelect", openChange: "openChange" }, viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, static: true }, { propertyName: "menuList", first: true, predicate: MenuListBodyComponent, descendants: true }], ngImport: i0, template: "<app-dropdown-base\r\n class=\"dropdown-menu\"\r\n [open]=\"open\"\r\n (openChange)=\"onBaseOpenChange($event)\"\r\n [panelTemplate]=\"panelTpl\"\r\n [panelWidthPx]=\"effectivePanelWidth\"\r\n [connectedPositions]=\"connectedPositions\"\r\n [pushConnectedOverlay]=\"true\"\r\n [hasBackdrop]=\"true\"\r\n [closeOnEscape]=\"true\"\r\n [bareOverlayPanel]=\"true\"\r\n>\r\n <span\r\n class=\"dropdown-menu__trigger-slot\"\r\n appDropdownTrigger\r\n (click)=\"onTriggerClick($event)\"\r\n [attr.aria-expanded]=\"open\"\r\n aria-haspopup=\"menu\"\r\n >\r\n <ng-content />\r\n </span>\r\n</app-dropdown-base>\r\n\r\n<ng-template #panelTpl>\r\n <div class=\"dropdown-menu__panel-inner\">\r\n <app-menu-list-body\r\n [items]=\"items\"\r\n [menuId]=\"resolvedMenuId\"\r\n [clickToOpen]=\"false\"\r\n (itemSelect)=\"onItemSelect($event)\"\r\n (closeRequest)=\"onCloseRequest()\"\r\n />\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:inline-block;max-width:100%;vertical-align:middle}.dropdown-menu{display:inline-flex;max-width:100%;min-width:0}.dropdown-menu__trigger-slot{display:inline-flex;max-width:100%;min-width:0;cursor:pointer}.dropdown-menu__panel-inner{box-sizing:border-box;min-width:0}\n"], dependencies: [{ kind: "component", type: DropdownBaseComponent, selector: "app-dropdown-base", inputs: ["open", "panelTemplate", "panelWidthPx", "closeOnEscape", "hasBackdrop", "connectedPositions", "pushConnectedOverlay", "scrollStrategy", "bareOverlayPanel"], outputs: ["openChange"] }, { kind: "component", type: MenuListBodyComponent, selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["selectionScrollHint", "itemSelect", "closeRequest", "submenuBack", "groupToggled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2192
2318
  }
2193
2319
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DropdownMenuComponent, decorators: [{
2194
2320
  type: Component,
@@ -10121,7 +10247,10 @@ function filterOneNode(node, qNormalized, rawQuery) {
10121
10247
  class MenuListComponent {
10122
10248
  constructor() {
10123
10249
  this.cdr = inject(ChangeDetectorRef);
10250
+ this.injector = inject(Injector);
10251
+ this.destroyRef = inject(DestroyRef);
10124
10252
  this.appTheme = input(...(ngDevMode ? [undefined, { debugName: "appTheme" }] : /* istanbul ignore next */ []));
10253
+ this.bodyRouteSyncGen = 0;
10125
10254
  this.items = [];
10126
10255
  this.menuId = 'app-menu';
10127
10256
  this.dense = false;
@@ -10143,8 +10272,16 @@ class MenuListComponent {
10143
10272
  this.closeRequest = new EventEmitter();
10144
10273
  this.submenuBack = new EventEmitter();
10145
10274
  this.groupToggled = output();
10275
+ /** Ver {@link MenuListBodyComponent.selectionScrollHint}. */
10276
+ this.selectionScrollHint = output();
10146
10277
  this.searchQuery = '';
10147
10278
  this.displayItems = [];
10279
+ this.destroyRef.onDestroy(() => {
10280
+ this.bodyRouteSyncGen++;
10281
+ });
10282
+ }
10283
+ ngAfterViewInit() {
10284
+ this.scheduleBodyRouteSelectionSync();
10148
10285
  }
10149
10286
  get showSearchField() {
10150
10287
  return this.searchable && !this.nested && !this.compressText;
@@ -10180,6 +10317,30 @@ class MenuListComponent {
10180
10317
  changes['persistGroupExpansion']) {
10181
10318
  this.cdr.markForCheck();
10182
10319
  }
10320
+ if (changes['selectedItemId'] ||
10321
+ changes['items'] ||
10322
+ changes['searchable'] ||
10323
+ changes['compressText'] ||
10324
+ changes['nested'] ||
10325
+ changes['groupCollapsible'] ||
10326
+ changes['groupDefaultExpansion'] ||
10327
+ changes['persistGroupExpansion'] ||
10328
+ changes['clickToOpen']) {
10329
+ this.scheduleBodyRouteSelectionSync();
10330
+ }
10331
+ }
10332
+ /**
10333
+ * O corpo do menu só existe após o primeiro render; no drawer mobile isso atrasa `ensureExpanded`
10334
+ * relativamente ao `ngOnChanges` do corpo — repetimos após `afterNextRender`.
10335
+ */
10336
+ scheduleBodyRouteSelectionSync() {
10337
+ const gen = ++this.bodyRouteSyncGen;
10338
+ afterNextRender(() => {
10339
+ if (gen !== this.bodyRouteSyncGen) {
10340
+ return;
10341
+ }
10342
+ this.body?.syncRouteSelectionExpansion();
10343
+ }, { injector: this.injector });
10183
10344
  }
10184
10345
  onSearchQueryInput(value) {
10185
10346
  this.searchQuery = value ?? '';
@@ -10193,6 +10354,17 @@ class MenuListComponent {
10193
10354
  focusFirstOption() {
10194
10355
  this.body?.focusFirstOption();
10195
10356
  }
10357
+ /**
10358
+ * Usado pela `app-sidebar` ao abrir o drawer móvel: garante {@link MenuListBodyComponent.syncRouteSelectionExpansion}
10359
+ * antes do scroll (grupos fechados em `sessionStorage` passam a abrir no caminho do item activo).
10360
+ */
10361
+ syncSelectionForMobileDrawerOpen() {
10362
+ if (this.body) {
10363
+ this.body.syncRouteSelectionExpansion();
10364
+ return;
10365
+ }
10366
+ this.scheduleBodyRouteSelectionSync();
10367
+ }
10196
10368
  syncDisplayItems() {
10197
10369
  if (!this.searchable || this.nested || this.compressText) {
10198
10370
  this.displayItems = [...(this.items ?? [])];
@@ -10202,12 +10374,12 @@ class MenuListComponent {
10202
10374
  }
10203
10375
  }
10204
10376
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10205
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuListComponent, isStandalone: true, selector: "app-menu-list", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, nested: { classPropertyName: "nested", publicName: "nested", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, compressText: { classPropertyName: "compressText", publicName: "compressText", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null }, persistGroupExpansion: { classPropertyName: "persistGroupExpansion", publicName: "persistGroupExpansion", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", closeRequest: "closeRequest", submenuBack: "submenuBack", groupToggled: "groupToggled" }, viewQueries: [{ propertyName: "body", first: true, predicate: MenuListBodyComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<app-menu-list-body\n [items]=\"displayItems\"\n [menuId]=\"menuId\"\n [nested]=\"nested\"\n [dense]=\"dense\"\n [compressText]=\"compressText\"\n [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\n [persistGroupExpansion]=\"persistGroupExpansion\"\n [clickToOpen]=\"clickToOpen\"\n [selectedItemId]=\"selectedItemId\"\n [appTheme]=\"appTheme()\"\n [expandAllGroupsInitially]=\"expandAllGroupsWhenSearching\"\n (itemSelect)=\"itemSelect.emit($event)\"\n (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"submenuBack.emit()\"\n (groupToggled)=\"groupToggled.emit($event)\"\n>\n @if (showSearchField) {\n <div class=\"menu-list__search\" role=\"search\">\n <app-text-field\n class=\"menu-list__search-field\"\n [id]=\"menuId + '-search'\"\n [name]=\"menuId + '-menu-search'\"\n size=\"sm\"\n [ngModel]=\"searchQuery\"\n (ngModelChange)=\"onSearchQueryInput($event)\"\n [placeholder]=\"searchPlaceholder\"\n [label]=\"''\"\n [showPrefixIcon]=\"true\"\n prefixIcon=\"fa-solid fa-magnifying-glass\"\n [clearable]=\"true\"\n [autocomplete]=\"false\"\n />\n </div>\n }\n @if (showSearchNoResults) {\n <p class=\"menu-list__search-empty\">Nenhum item encontrado</p>\n }\n</app-menu-list-body>\n", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TextFieldComponent, selector: "app-text-field", inputs: ["maxLength"] }, { kind: "component", type: MenuListBodyComponent, selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10377
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuListComponent, isStandalone: true, selector: "app-menu-list", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, nested: { classPropertyName: "nested", publicName: "nested", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, compressText: { classPropertyName: "compressText", publicName: "compressText", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null }, persistGroupExpansion: { classPropertyName: "persistGroupExpansion", publicName: "persistGroupExpansion", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", closeRequest: "closeRequest", submenuBack: "submenuBack", groupToggled: "groupToggled", selectionScrollHint: "selectionScrollHint" }, viewQueries: [{ propertyName: "body", first: true, predicate: MenuListBodyComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<app-menu-list-body\n [items]=\"displayItems\"\n [menuId]=\"menuId\"\n [nested]=\"nested\"\n [dense]=\"dense\"\n [compressText]=\"compressText\"\n [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\n [persistGroupExpansion]=\"persistGroupExpansion\"\n [clickToOpen]=\"clickToOpen\"\n [selectedItemId]=\"selectedItemId\"\n [appTheme]=\"appTheme()\"\n [expandAllGroupsInitially]=\"expandAllGroupsWhenSearching\"\n (itemSelect)=\"itemSelect.emit($event)\"\n (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"submenuBack.emit()\"\n (groupToggled)=\"groupToggled.emit($event)\"\n (selectionScrollHint)=\"selectionScrollHint.emit()\"\n>\n @if (showSearchField) {\n <div class=\"menu-list__search\" role=\"search\">\n <app-text-field\n class=\"menu-list__search-field\"\n [id]=\"menuId + '-search'\"\n [name]=\"menuId + '-menu-search'\"\n size=\"sm\"\n [ngModel]=\"searchQuery\"\n (ngModelChange)=\"onSearchQueryInput($event)\"\n [placeholder]=\"searchPlaceholder\"\n [label]=\"''\"\n [showPrefixIcon]=\"true\"\n prefixIcon=\"fa-solid fa-magnifying-glass\"\n [clearable]=\"true\"\n [autocomplete]=\"false\"\n />\n </div>\n }\n @if (showSearchNoResults) {\n <p class=\"menu-list__search-empty\">Nenhum item encontrado</p>\n }\n</app-menu-list-body>\n", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TextFieldComponent, selector: "app-text-field", inputs: ["maxLength"] }, { kind: "component", type: MenuListBodyComponent, selector: "app-menu-list-body", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "expandAllGroupsInitially"], outputs: ["selectionScrollHint", "itemSelect", "closeRequest", "submenuBack", "groupToggled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10206
10378
  }
10207
10379
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuListComponent, decorators: [{
10208
10380
  type: Component,
10209
- args: [{ selector: 'app-menu-list', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, TextFieldComponent, MenuListBodyComponent], template: "<app-menu-list-body\n [items]=\"displayItems\"\n [menuId]=\"menuId\"\n [nested]=\"nested\"\n [dense]=\"dense\"\n [compressText]=\"compressText\"\n [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\n [persistGroupExpansion]=\"persistGroupExpansion\"\n [clickToOpen]=\"clickToOpen\"\n [selectedItemId]=\"selectedItemId\"\n [appTheme]=\"appTheme()\"\n [expandAllGroupsInitially]=\"expandAllGroupsWhenSearching\"\n (itemSelect)=\"itemSelect.emit($event)\"\n (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"submenuBack.emit()\"\n (groupToggled)=\"groupToggled.emit($event)\"\n>\n @if (showSearchField) {\n <div class=\"menu-list__search\" role=\"search\">\n <app-text-field\n class=\"menu-list__search-field\"\n [id]=\"menuId + '-search'\"\n [name]=\"menuId + '-menu-search'\"\n size=\"sm\"\n [ngModel]=\"searchQuery\"\n (ngModelChange)=\"onSearchQueryInput($event)\"\n [placeholder]=\"searchPlaceholder\"\n [label]=\"''\"\n [showPrefixIcon]=\"true\"\n prefixIcon=\"fa-solid fa-magnifying-glass\"\n [clearable]=\"true\"\n [autocomplete]=\"false\"\n />\n </div>\n }\n @if (showSearchNoResults) {\n <p class=\"menu-list__search-empty\">Nenhum item encontrado</p>\n }\n</app-menu-list-body>\n", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"] }]
10210
- }], propDecorators: { appTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTheme", required: false }] }], items: [{
10381
+ args: [{ selector: 'app-menu-list', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, TextFieldComponent, MenuListBodyComponent], template: "<app-menu-list-body\n [items]=\"displayItems\"\n [menuId]=\"menuId\"\n [nested]=\"nested\"\n [dense]=\"dense\"\n [compressText]=\"compressText\"\n [groupCollapsible]=\"groupCollapsible\"\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\n [persistGroupExpansion]=\"persistGroupExpansion\"\n [clickToOpen]=\"clickToOpen\"\n [selectedItemId]=\"selectedItemId\"\n [appTheme]=\"appTheme()\"\n [expandAllGroupsInitially]=\"expandAllGroupsWhenSearching\"\n (itemSelect)=\"itemSelect.emit($event)\"\n (closeRequest)=\"closeRequest.emit()\"\n (submenuBack)=\"submenuBack.emit()\"\n (groupToggled)=\"groupToggled.emit($event)\"\n (selectionScrollHint)=\"selectionScrollHint.emit()\"\n>\n @if (showSearchField) {\n <div class=\"menu-list__search\" role=\"search\">\n <app-text-field\n class=\"menu-list__search-field\"\n [id]=\"menuId + '-search'\"\n [name]=\"menuId + '-menu-search'\"\n size=\"sm\"\n [ngModel]=\"searchQuery\"\n (ngModelChange)=\"onSearchQueryInput($event)\"\n [placeholder]=\"searchPlaceholder\"\n [label]=\"''\"\n [showPrefixIcon]=\"true\"\n prefixIcon=\"fa-solid fa-magnifying-glass\"\n [clearable]=\"true\"\n [autocomplete]=\"false\"\n />\n </div>\n }\n @if (showSearchNoResults) {\n <p class=\"menu-list__search-empty\">Nenhum item encontrado</p>\n }\n</app-menu-list-body>\n", styles: ["@charset \"UTF-8\";@keyframes app-sidebar-nav-reveal-in{0%{opacity:0;transform:translate3d(-.45rem,0,0)}to{opacity:1;transform:translateZ(0)}}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list{background:var(--app-color-surface, #ffffff);border:1px solid var(--app-color-border-subtle, rgba(26, 47, 69, .12));border-radius:10px;box-shadow:0 10px 28px -14px #0f172a29;max-height:min(70vh,22rem);overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0;overflow:hidden;gap:.35rem;padding:.45rem 0;outline:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.menu-list--dense{padding:.2rem 0;gap:0}.menu-list--dense .menu-list__items{gap:0}.menu-list--dense.menu-list--compress-text .menu-list__items{gap:.25rem}.menu-list__toolbar{flex:0 0 auto;min-width:0}.menu-list__viewport{flex:1 1 auto;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 34%,transparent) transparent}.menu-list__viewport::-webkit-scrollbar{width:4px;height:4px}.menu-list__viewport::-webkit-scrollbar-track{background:transparent}.menu-list__viewport::-webkit-scrollbar-thumb{border-radius:999px;background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 40%,transparent)}.menu-list__viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--app-color-text-primary, #1a2f45) 55%,transparent)}.menu-list__items{display:flex;flex-direction:column;gap:.12rem;min-width:0}.menu-list__search{margin:0 .35rem .12rem;min-width:0;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text}.menu-list__search-field{display:block;width:100%}.menu-list__search-empty{margin:-.05rem .75rem 0;padding:0 0 .15rem;font-size:.75rem;line-height:1.35;font-weight:400;color:var(--app-color-text-muted, #6b8299);opacity:.88}.menu-list__group-row{display:block;width:100%}.menu-list__group-row--pinned .menu-list__group-label{color:var(--app-color-nav-group-heading, #9ca3af)}.menu-list__submenu-wrap{position:relative;display:block}.menu-list__option{display:flex;align-items:center;box-sizing:border-box;gap:.6875rem;margin:0 .25rem;padding:.5625rem .65rem;border-radius:8px;cursor:pointer;color:var(--app-color-text-primary, #1a2f45);background:transparent;border:1px solid transparent;text-align:left;font:inherit;line-height:1.25;transition:background-color .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.menu-list__option:focus-visible{outline:2px solid var(--app-color-focus-ring-strong, rgba(43, 127, 217, .45));outline-offset:1px}.menu-list__option:hover:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0b}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading){background:#0f172a0e;border-color:transparent}.menu-list__option.menu-list__option--active:not(.menu-list__option--disabled):not(.menu-list__option--loading):not(.menu-list__option--selected){box-shadow:none}.menu-list__option.menu-list__option--disabled{cursor:not-allowed;color:var(--app-color-text-muted, #6b8299);background:transparent;opacity:.72}.menu-list__option.menu-list__option--loading{cursor:wait;opacity:.92;pointer-events:none}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading){color:var(--app-color-error, #b91c1c)}.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading):hover,.menu-list__option.menu-list__option--danger:not(.menu-list__option--disabled):not(.menu-list__option--loading).menu-list__option--active{background:var(--app-color-error-bg-subtle, rgba(185, 28, 28, .12));border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-error-border, #dc2626)}.menu-list__option--submenu{padding-right:.35rem}.menu-list__option--selected:not(.menu-list__option--disabled){background:color-mix(in srgb,var(--app-color-primary) 10%,transparent);border-radius:8px;border-color:transparent;box-shadow:inset 2px 0 0 0 var(--app-color-primary, #2b7fd9)}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__label{color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 88%,var(--app-color-nav-option-label, #374151));font-weight:500}.menu-list__option--selected:not(.menu-list__option--disabled) .menu-list__icon{color:var(--app-color-primary, #2b7fd9)}.menu-list__option:not(.menu-list__option--danger):not(.menu-list__option--disabled):not(.menu-list__option--selected) .menu-list__label{color:var(--app-color-nav-option-label, #374151)}.menu-list--compress-text .menu-list__label,.menu-list--compress-text .menu-list__description{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.menu-list--compress-text .menu-list__text,.menu-list--compress-text .menu-list__submenu-chevron{display:none}.menu-list--compress-text .menu-list__submenu-wrap{width:100%}.menu-list--compress-text .menu-list__option{justify-content:center;align-items:center;text-align:center;width:calc(100% - .5rem);max-width:100%;box-sizing:border-box;margin-left:.25rem;margin-right:.25rem;padding:.5rem .35rem}.menu-list--compress-text .menu-list__option--submenu{padding-left:.35rem;padding-right:.35rem}.menu-list--compress-text .menu-list__icon{flex:0 0 auto;width:auto;min-width:1.75rem;display:inline-flex;align-items:center;justify-content:center;padding-top:0}.menu-list__submenu-chevron{flex:0 0 auto;margin-left:auto;padding-left:.35rem;font-size:1rem;line-height:1;color:var(--app-color-text-muted, #6b8299);opacity:.85;display:inline-flex;align-items:center;justify-content:center}.menu-list__submenu-chevron i{font-size:.68rem;line-height:1}.menu-list__icon{flex:0 0 auto;width:1.25rem;height:1.25rem;min-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;text-align:center;color:color-mix(in srgb,var(--app-color-primary, #2b7fd9) 78%,var(--app-color-text-muted, #6b8299));line-height:1;transition:color .18s ease,opacity .18s ease}.menu-list__icon i{display:flex;align-items:center;justify-content:center;width:100%;height:100%;line-height:1;font-size:.95rem;margin-block:auto;flex-shrink:0}.menu-list__option--disabled .menu-list__icon{opacity:.55}.menu-list__icon--spin i{animation:menu-list-spin .8s linear infinite}.menu-list__text{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}.menu-list__label{font-size:.875rem;font-weight:400;line-height:1.25rem;display:inline-flex;align-items:center;min-height:1.25rem;box-sizing:border-box;padding-top:.5rem!important}.menu-list--nested .menu-list__label{font-weight:400;padding-top:.5rem!important}.menu-list--nested .menu-list__icon{transform:translateY(.125rem)}.menu-list__description{font-size:.75rem;color:var(--app-color-text-muted, #6b8299);line-height:1.3}.menu-list:not(.menu-list--compress-text){animation:app-sidebar-nav-reveal-in .45s cubic-bezier(.16,1,.32,1) both}@media(prefers-reduced-motion:reduce){.menu-list:not(.menu-list--compress-text){animation:none}}:host-context(.app-drawer__body) .menu-list__label{padding-top:.5rem!important}:host-context(.app-drawer__body) .menu-list__icon{transform:translateY(.1875rem)}@media(max-width:767.98px){.menu-list.menu-list--nested .menu-list__label{padding-top:.4rem!important}.menu-list.menu-list--nested .menu-list__icon{transform:translateY(.1875rem)}}.menu-submenu__panel{box-sizing:border-box;min-width:0;padding:0;background:transparent;border:none;box-shadow:none;border-radius:10px;overflow:hidden}@keyframes menu-list-spin{to{transform:rotate(360deg)}}:host ::ng-deep .menu-submenu__cdk-panel{background:transparent;box-shadow:none;border-radius:10px}\n"] }]
10382
+ }], ctorParameters: () => [], propDecorators: { appTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTheme", required: false }] }], items: [{
10211
10383
  type: Input,
10212
10384
  args: [{ required: true }]
10213
10385
  }], menuId: [{
@@ -10244,7 +10416,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
10244
10416
  type: Output
10245
10417
  }], submenuBack: [{
10246
10418
  type: Output
10247
- }], groupToggled: [{ type: i0.Output, args: ["groupToggled"] }], body: [{
10419
+ }], groupToggled: [{ type: i0.Output, args: ["groupToggled"] }], selectionScrollHint: [{ type: i0.Output, args: ["selectionScrollHint"] }], body: [{
10248
10420
  type: ViewChild,
10249
10421
  args: [MenuListBodyComponent]
10250
10422
  }] } });
@@ -10327,7 +10499,7 @@ class ContextMenuComponent {
10327
10499
  this.disposeOverlay();
10328
10500
  }
10329
10501
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContextMenuComponent, deps: [{ token: i1$1.Overlay }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
10330
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ContextMenuComponent, isStandalone: true, selector: "app-context-menu", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, viewQueries: [{ propertyName: "menuTpl", first: true, predicate: ["menuTpl"], descendants: true, static: true }, { propertyName: "menuList", first: true, predicate: MenuListComponent, descendants: true }], ngImport: i0, template: "<span class=\"context-menu__host\" (contextmenu)=\"onContextMenu($event)\">\r\n <ng-content />\r\n</span>\r\n\r\n<ng-template #menuTpl>\r\n <div class=\"context-menu__surface\" [ngClass]=\"panelThemeNgClass()\" (click)=\"$event.stopPropagation()\">\r\n <app-menu-list\r\n [appTheme]=\"effectiveThemeId()\"\r\n [items]=\"items\"\r\n [menuId]=\"resolvedMenuId\"\r\n [clickToOpen]=\"false\"\r\n (itemSelect)=\"onItemSelect($event)\"\r\n (closeRequest)=\"onCloseRequest()\"\r\n />\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:contents}.context-menu__host{display:contents}.context-menu__surface{box-sizing:border-box;min-width:12.5rem;max-width:min(100vw - 1rem,22rem)}\n"], dependencies: [{ kind: "component", type: MenuListComponent, selector: "app-menu-list", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "searchable", "searchPlaceholder"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10502
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ContextMenuComponent, isStandalone: true, selector: "app-context-menu", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, viewQueries: [{ propertyName: "menuTpl", first: true, predicate: ["menuTpl"], descendants: true, static: true }, { propertyName: "menuList", first: true, predicate: MenuListComponent, descendants: true }], ngImport: i0, template: "<span class=\"context-menu__host\" (contextmenu)=\"onContextMenu($event)\">\r\n <ng-content />\r\n</span>\r\n\r\n<ng-template #menuTpl>\r\n <div class=\"context-menu__surface\" [ngClass]=\"panelThemeNgClass()\" (click)=\"$event.stopPropagation()\">\r\n <app-menu-list\r\n [appTheme]=\"effectiveThemeId()\"\r\n [items]=\"items\"\r\n [menuId]=\"resolvedMenuId\"\r\n [clickToOpen]=\"false\"\r\n (itemSelect)=\"onItemSelect($event)\"\r\n (closeRequest)=\"onCloseRequest()\"\r\n />\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:contents}.context-menu__host{display:contents}.context-menu__surface{box-sizing:border-box;min-width:12.5rem;max-width:min(100vw - 1rem,22rem)}\n"], dependencies: [{ kind: "component", type: MenuListComponent, selector: "app-menu-list", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "searchable", "searchPlaceholder"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled", "selectionScrollHint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10331
10503
  }
10332
10504
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContextMenuComponent, decorators: [{
10333
10505
  type: Component,
@@ -11196,6 +11368,7 @@ class AppSidebarComponent {
11196
11368
  this.cdr = inject(ChangeDetectorRef);
11197
11369
  this.destroyRef = inject(DestroyRef);
11198
11370
  this.hostEl = inject((ElementRef));
11371
+ this.injector = inject(Injector);
11199
11372
  this.renderer = inject(Renderer2);
11200
11373
  /** Igual a `[appTheme]` / {@link ThemeDirective}: paleta explícita no host; omitir = herdar / serviço. */
11201
11374
  this.appTheme = input(...(ngDevMode ? [undefined, { debugName: "appTheme" }] : /* istanbul ignore next */ []));
@@ -11204,6 +11377,12 @@ class AppSidebarComponent {
11204
11377
  this.selectedItemId = null;
11205
11378
  /** Modo estreito: só ícones + `compressText` na lista (rótulos via `title` / `aria-label`). */
11206
11379
  this.collapsed = false;
11380
+ /**
11381
+ * Ligado ao estado do drawer no telemóvel (ex.: `mobileNavOpen` do `app-shell`).
11382
+ * Em cada transição para `true`, volta a agendar o scroll até ao item activo — útil porque `selectedItemId`
11383
+ * pode não mudar entre aberturas e o menu pode ser recriado dentro do `@if (open)` do drawer.
11384
+ */
11385
+ this.mobileNavOpenPulse = false;
11207
11386
  /** Repassado a {@link MenuListComponent.searchable}: campo de pesquisa na lista da lateral. */
11208
11387
  this.searchable = false;
11209
11388
  /**
@@ -11230,7 +11409,15 @@ class AppSidebarComponent {
11230
11409
  this.listCompressText = signal(false, ...(ngDevMode ? [{ debugName: "listCompressText" }] : /* istanbul ignore next */ []));
11231
11410
  this.listRevealTimeoutId = null;
11232
11411
  this.scrollRestoreTimeoutId = null;
11233
- this.destroyRef.onDestroy(() => this.clearListRevealTimeout());
11412
+ /** Invalida tentativas de scroll pendentes (ex.: novo agendamento ou destroy). */
11413
+ this.scrollToSelectedGeneration = 0;
11414
+ /** `setTimeout` extra ao abrir o drawer — animação (~240ms) e flex podem atrasar métricas do scroll. */
11415
+ this.drawerScrollAssistTimeouts = [];
11416
+ this.destroyRef.onDestroy(() => {
11417
+ this.clearListRevealTimeout();
11418
+ this.clearDrawerScrollAssistTimeouts();
11419
+ this.scrollToSelectedGeneration++;
11420
+ });
11234
11421
  effect(() => {
11235
11422
  applyOptionalThemeHostClasses(this.renderer, this.hostEl.nativeElement, this.appTheme());
11236
11423
  });
@@ -11242,6 +11429,8 @@ class AppSidebarComponent {
11242
11429
  }
11243
11430
  ngAfterViewInit() {
11244
11431
  this.scheduleSidebarHeadLayoutGuards();
11432
+ /** Drawer mobile `@if (open)` remonta a sidebar — após a vista, alinhar scroll como no desktop. */
11433
+ this.scheduleScrollToSelected();
11245
11434
  }
11246
11435
  ngOnChanges(changes) {
11247
11436
  if (changes['selectedItemId'] || changes['items']) {
@@ -11250,15 +11439,30 @@ class AppSidebarComponent {
11250
11439
  if (changes['collapsed']) {
11251
11440
  this.scheduleSidebarHeadLayoutGuards();
11252
11441
  }
11253
- /** Acompanhar a selecção na lista expandida (evita item «cortado» a meio da viewport). */
11254
- if ((changes['selectedItemId'] || changes['items']) &&
11255
- !this.collapsed &&
11256
- !this.listCompressText()) {
11257
- queueMicrotask(() => {
11258
- requestAnimationFrame(() => {
11259
- requestAnimationFrame(() => this.scrollSidebarToSelectedItem());
11260
- });
11261
- });
11442
+ /**
11443
+ * Lista expandida: evita scroll durante `listCompressText` transitório (animação de largura).
11444
+ * Modo rail (`collapsed`): ícones continuam em `.menu-list__viewport` — faz scroll para o `--selected`
11445
+ * ficar inteiro (ícone «cortado» ao clicar ou ao mudar a rota).
11446
+ */
11447
+ if (changes['selectedItemId'] || changes['items']) {
11448
+ if (this.collapsed || !this.listCompressText()) {
11449
+ this.scheduleScrollToSelected();
11450
+ }
11451
+ }
11452
+ const pulseCh = changes['mobileNavOpenPulse'];
11453
+ if (pulseCh &&
11454
+ this.mobileNavOpenPulse &&
11455
+ pulseCh.previousValue !== true) {
11456
+ /**
11457
+ * Primeiro expandir grupos no caminho da selecção (persistidos fechados); `syncRouteSelectionExpansion`
11458
+ * emite `selectionScrollHint` e só então o scroll encontra `.menu-list__option--selected`.
11459
+ */
11460
+ afterNextRender(() => {
11461
+ this.menuList?.syncSelectionForMobileDrawerOpen();
11462
+ if (!this.menuList) {
11463
+ this.scheduleScrollToSelected();
11464
+ }
11465
+ }, { injector: this.injector });
11262
11466
  }
11263
11467
  const collapsedCh = changes['collapsed'];
11264
11468
  if (!collapsedCh) {
@@ -11284,27 +11488,110 @@ class AppSidebarComponent {
11284
11488
  /** Depois da animação de largura (~120ms) + reflow dos rótulos — mesma ordem que `_sidebar-reveal.scss`. */
11285
11489
  this.scrollRestoreTimeoutId = setTimeout(() => {
11286
11490
  this.scrollRestoreTimeoutId = null;
11287
- requestAnimationFrame(() => {
11288
- requestAnimationFrame(() => this.scrollSidebarToSelectedItem());
11289
- });
11491
+ this.scheduleScrollToSelected();
11290
11492
  }, APP_SIDEBAR_LAYOUT_TRANSITION_MS);
11291
11493
  }, APP_SIDEBAR_NAV_REVEAL_TOTAL_MS);
11292
11494
  }
11293
11495
  /**
11294
- * Garante que o item `--selected` fica inteiro na área útil (margem + cabeçalho sticky),
11295
- * com da opção vizinha visível quando scroll, e movimento suave.
11496
+ * Agenda scroll até ao `--selected` depois do próximo render (filhos OnPush) e reintenta em `rAF`
11497
+ * até o elemento existir necessário no drawer mobile, onde o menu acaba de montar.
11296
11498
  */
11297
- scrollSidebarToSelectedItem() {
11499
+ /**
11500
+ * Repete o scroll quando o utilizador clica num item já activo mas «cortado» (`selectedItemId` não muda).
11501
+ */
11502
+ onSidebarItemSelect(id) {
11503
+ this.itemSelect.emit(id);
11504
+ this.scheduleScrollToSelected();
11505
+ }
11506
+ /** Também ligado a `(selectionScrollHint)` em `app-menu-list` para o drawer mobile. */
11507
+ scheduleScrollToSelected() {
11508
+ this.clearDrawerScrollAssistTimeouts();
11509
+ const gen = ++this.scrollToSelectedGeneration;
11510
+ afterNextRender(() => {
11511
+ if (gen !== this.scrollToSelectedGeneration) {
11512
+ return;
11513
+ }
11514
+ /**
11515
+ * Os timeouts do drawer **têm** de ser registados aqui — não no instante inicial da chamada:
11516
+ * antes do próximo render o host pode ainda não estar sob `.app-drawer__body`, e na 2.ª abertura
11517
+ * do menu o `closest` falhava no schedule e os pulsos deixavam de existir.
11518
+ */
11519
+ if (this.isInsideMobileDrawer()) {
11520
+ const delaysMs = [90, 260, 420, 600];
11521
+ for (const ms of delaysMs) {
11522
+ const tid = window.setTimeout(() => {
11523
+ if (gen !== this.scrollToSelectedGeneration) {
11524
+ return;
11525
+ }
11526
+ queueMicrotask(() => {
11527
+ requestAnimationFrame(() => {
11528
+ this.runScrollToSelectedRetry(gen, 0);
11529
+ });
11530
+ });
11531
+ }, ms);
11532
+ this.drawerScrollAssistTimeouts.push(tid);
11533
+ }
11534
+ }
11535
+ queueMicrotask(() => {
11536
+ requestAnimationFrame(() => {
11537
+ requestAnimationFrame(() => {
11538
+ this.runScrollToSelectedRetry(gen, 0);
11539
+ });
11540
+ });
11541
+ });
11542
+ }, { injector: this.injector });
11543
+ }
11544
+ static { this.SCROLL_TO_SELECTED_MAX_ATTEMPTS = 48; }
11545
+ static { this.SCROLL_TO_SELECTED_MAX_ATTEMPTS_DRAWER = 96; }
11546
+ /** Sidebar projectada em `.app-drawer__body` — animação do painel e `overflow` do shell afectam o layout. */
11547
+ isInsideMobileDrawer() {
11548
+ return !!this.hostEl.nativeElement.closest('.app-drawer__body');
11549
+ }
11550
+ clearDrawerScrollAssistTimeouts() {
11551
+ for (const tid of this.drawerScrollAssistTimeouts) {
11552
+ clearTimeout(tid);
11553
+ }
11554
+ this.drawerScrollAssistTimeouts = [];
11555
+ }
11556
+ runScrollToSelectedRetry(gen, attempt) {
11557
+ if (gen !== this.scrollToSelectedGeneration) {
11558
+ return;
11559
+ }
11560
+ if (this.selectedItemId == null) {
11561
+ return;
11562
+ }
11563
+ /** Rail: `compressText` fica activo com `collapsed`; ainda assim queremos scroll até ao ícone. */
11564
+ if (!this.collapsed && this.listCompressText()) {
11565
+ return;
11566
+ }
11567
+ const maxAttempts = this.isInsideMobileDrawer()
11568
+ ? AppSidebarComponent.SCROLL_TO_SELECTED_MAX_ATTEMPTS_DRAWER
11569
+ : AppSidebarComponent.SCROLL_TO_SELECTED_MAX_ATTEMPTS;
11298
11570
  const scroll = this.getSidebarMenuListViewport();
11299
- if (!scroll || this.selectedItemId == null || this.collapsed) {
11571
+ if (!scroll) {
11572
+ if (attempt < maxAttempts) {
11573
+ requestAnimationFrame(() => this.runScrollToSelectedRetry(gen, attempt + 1));
11574
+ }
11575
+ return;
11576
+ }
11577
+ /** Flex / animação do drawer: viewport pode ainda ter altura 0 no primeiro frame. */
11578
+ if (scroll.clientHeight < 4 && attempt < maxAttempts) {
11579
+ requestAnimationFrame(() => this.runScrollToSelectedRetry(gen, attempt + 1));
11300
11580
  return;
11301
11581
  }
11302
11582
  const matches = scroll.querySelectorAll('.menu-list__option--selected');
11303
11583
  if (matches.length === 0) {
11584
+ if (attempt < maxAttempts) {
11585
+ requestAnimationFrame(() => this.runScrollToSelectedRetry(gen, attempt + 1));
11586
+ }
11304
11587
  return;
11305
11588
  }
11306
11589
  const selected = matches[matches.length - 1];
11307
11590
  this.scrollSidebarScrollAreaToElement(scroll, selected);
11591
+ if (this.isInsideMobileDrawer()) {
11592
+ /** Reforço nativo após cálculo manual — durante `transform` do painel o layout pode mentir um frame. */
11593
+ selected.scrollIntoView({ block: 'nearest', behavior: 'auto' });
11594
+ }
11308
11595
  }
11309
11596
  /** Após clicar num grupo colapsável: leva o cabeçalho do grupo para a zona visível (como o item seleccionado). */
11310
11597
  onMenuGroupToggled(groupId) {
@@ -11332,17 +11619,18 @@ class AppSidebarComponent {
11332
11619
  return this.hostEl.nativeElement.querySelector('.menu-list__viewport');
11333
11620
  }
11334
11621
  scrollSidebarScrollAreaToElement(scroll, target) {
11335
- if (this.collapsed) {
11336
- return;
11337
- }
11338
11622
  const marginCss = 10;
11623
+ /** No rail os ícones são densos — um pouco mais de folga no topo evita meio-ícone «cortado». */
11624
+ const topPadExtra = this.collapsed ? 8 : 0;
11625
+ /** Folga inferior — no drawer em lista completa puxamos mais para o item não ficar no limite. */
11626
+ const bottomComfortPx = Math.max(marginCss, this.collapsed ? marginCss : this.isInsideMobileDrawer() ? 52 : 44);
11339
11627
  const basePeek = this.getMenuNeighborPeekHalfHeights(target);
11340
11628
  /** Cabeçalhos de grupo: mais folga vertical (~vizinho + boost) para não ficarem «apertados». */
11341
11629
  const groupPeekBoost = target.classList.contains('menu-list__group-row') ? 22 : 0;
11342
11630
  const peekAbove = basePeek.peekAbove + groupPeekBoost;
11343
11631
  const peekBelow = basePeek.peekBelow + groupPeekBoost;
11344
11632
  /** Cabeçalho está fora do scroll — só margem no topo da viewport de scroll. */
11345
- const topPad = marginCss;
11633
+ const topPad = marginCss + topPadExtra;
11346
11634
  const scrRect = scroll.getBoundingClientRect();
11347
11635
  const elRect = target.getBoundingClientRect();
11348
11636
  const elTop = scroll.scrollTop + (elRect.top - scrRect.top);
@@ -11354,8 +11642,8 @@ class AppSidebarComponent {
11354
11642
  if (elTop < viewTop + topPad) {
11355
11643
  nextTop = elTop - topPad - peekAbove;
11356
11644
  }
11357
- else if (elBottom > viewBottom - marginCss) {
11358
- nextTop = elBottom - scroll.clientHeight + marginCss + peekBelow;
11645
+ else if (elBottom > viewBottom - bottomComfortPx) {
11646
+ nextTop = elBottom - scroll.clientHeight + bottomComfortPx + peekBelow;
11359
11647
  }
11360
11648
  else {
11361
11649
  return;
@@ -11365,7 +11653,8 @@ class AppSidebarComponent {
11365
11653
  if (Math.abs(nextTop - scroll.scrollTop) < 1) {
11366
11654
  return;
11367
11655
  }
11368
- scroll.scrollTo({ top: nextTop, behavior: 'smooth' });
11656
+ const behavior = this.isInsideMobileDrawer() ? 'auto' : 'smooth';
11657
+ scroll.scrollTo({ top: nextTop, behavior });
11369
11658
  }
11370
11659
  /**
11371
11660
  * Metade da altura da linha vizinha (opção ou cabeçalho de grupo) na mesma lista (fallback em px).
@@ -11496,11 +11785,11 @@ class AppSidebarComponent {
11496
11785
  }
11497
11786
  }
11498
11787
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AppSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11499
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AppSidebarComponent, isStandalone: true, selector: "app-sidebar", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, usesOnChanges: true, ngImport: i0, template: "<nav class=\"app-sidebar app-nav-surface\" [class.app-sidebar--collapsed]=\"collapsed\"\r\n [attr.aria-label]=\"'Navega\u00E7\u00E3o principal'\">\r\n <!-- Cabe\u00E7alho fixo; pesquisa fixa em `.menu-list__toolbar`; barra s\u00F3 em `.menu-list__viewport`. -->\r\n <div class=\"app-sidebar__head\" data-app-sidebar-head=\"\" translate=\"no\">\r\n <div class=\"app-sidebar__brand\"><ng-content select=\"[appSidebarBrand]\" /></div>\r\n <div class=\"app-sidebar__toolbar\"><ng-content select=\"[appSidebarToolbar]\" /></div>\r\n </div>\r\n <div class=\"app-sidebar__scroll\">\r\n <app-menu-list\r\n class=\"app-sidebar__list\"\r\n [appTheme]=\"appTheme()\"\r\n [items]=\"items\"\r\n [menuId]=\"menuId\"\r\n [dense]=\"collapsed\"\r\n [compressText]=\"listCompressText()\"\r\n [searchable]=\"searchable\"\r\n [clickToOpen]=\"clickToOpen\"\r\n [groupCollapsible]=\"groupCollapsible\"\r\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\r\n [selectedItemId]=\"selectedItemId\"\r\n (itemSelect)=\"itemSelect.emit($event)\"\r\n (groupToggled)=\"onMenuGroupToggled($event)\"\r\n />\r\n </div>\r\n</nav>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;flex:1 1 auto;align-self:stretch;min-width:0;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.app-sidebar{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;padding:.65rem .35rem .65rem .5rem;background:var(--app-color-nav-shell-bg);border-right:1px solid var(--app-color-nav-border-subtle)}.app-sidebar--collapsed{padding-inline:.425rem}.app-sidebar__head[data-app-sidebar-head]{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.35rem;width:100%;min-height:2.35rem;background:var(--app-color-nav-shell-bg);padding:0 .1rem .45rem;padding-inline-start:.85rem!important;padding-inline-end:calc(.1rem + 4px)!important;box-sizing:border-box;direction:ltr;unicode-bidi:isolate;flex-direction:row!important;justify-content:flex-start!important;direction:ltr!important}.app-sidebar--collapsed .app-sidebar__head[data-app-sidebar-head]{justify-content:center!important;padding-inline-start:0!important;padding-inline-end:4px!important;gap:0}.app-sidebar__brand{order:0;flex:1 1 0%;min-width:0;align-self:center;display:flex;justify-content:flex-start;align-items:center;padding:0;box-sizing:border-box;font-size:.95rem;font-weight:700;line-height:1.25;color:var(--app-color-text-primary, #1a2f45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start!important}.app-sidebar__brand>*{text-align:inherit!important;margin-inline:0!important;margin-inline-start:0!important;margin-inline-end:0!important;padding-inline-start:0!important;padding-inline-end:0!important;box-sizing:border-box;min-width:0;align-self:center;max-width:100%}.app-sidebar__brand ::ng-deep [appSidebarBrand]{display:inline-flex!important;flex-direction:row!important;justify-content:flex-start!important;align-items:center!important;align-self:center!important;margin-inline-start:0!important;margin-inline-end:auto!important;margin-left:0!important;margin-right:auto!important;text-align:start!important;width:auto!important;max-width:100%!important;min-width:0!important;flex:1 1 0%!important;box-sizing:border-box}.app-sidebar__brand:empty{display:none}.app-sidebar--collapsed .app-sidebar__brand:not(:empty){display:none}.app-sidebar__toolbar{order:1;flex:0 0 auto;flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;align-self:stretch;min-width:0;padding:0;box-sizing:border-box;margin-inline-start:auto!important}.app-sidebar__toolbar:empty{display:none}.app-sidebar--collapsed .app-sidebar__toolbar:not(:empty){flex:1 1 auto!important;width:100%!important;min-width:0!important;margin-inline-start:0!important;justify-content:center!important}.app-sidebar--collapsed .app-sidebar__toolbar ::ng-deep [appSidebarToolbar]:not(app-shell-sidebar-toggle)>:not(app-shell-sidebar-toggle){display:none!important}.app-sidebar__scroll{flex:1 1 auto;min-height:0;overflow:hidden;display:flex;flex-direction:column}.app-sidebar__list{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box}@media(min-width:52.0625rem){.app-sidebar .app-sidebar__head[data-app-sidebar-head]{padding-top:.2rem}.app-sidebar .app-sidebar__brand ::ng-deep [appSidebarBrand]{min-height:2.35rem!important;height:2.35rem!important;line-height:1!important}}:host-context(.app-drawer__body) .app-sidebar__head[data-app-sidebar-head]{justify-content:flex-start!important;align-items:center!important;padding-top:0!important;padding-bottom:.35rem!important;z-index:1!important}:host-context(.app-drawer__body) .app-sidebar__brand{justify-content:flex-start!important;flex:1 1 0%!important;min-width:0!important;text-align:start!important}:host-context(.app-drawer__body) .app-sidebar__toolbar:not(:empty){margin-inline-start:auto!important;justify-content:flex-end!important;align-self:stretch!important}:host-context(.app-drawer__body) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;min-height:auto!important;height:auto!important;line-height:1.25!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__label{padding-top:.72rem!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__icon{transform:translateY(.1875rem)}:host-context(.app-shell__sidebar) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;text-align:start!important}\n"], dependencies: [{ kind: "component", type: MenuListComponent, selector: "app-menu-list", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "searchable", "searchPlaceholder"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11788
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AppSidebarComponent, isStandalone: true, selector: "app-sidebar", inputs: { appTheme: { classPropertyName: "appTheme", publicName: "appTheme", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null }, menuId: { classPropertyName: "menuId", publicName: "menuId", isSignal: false, isRequired: false, transformFunction: null }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: false, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, mobileNavOpenPulse: { classPropertyName: "mobileNavOpenPulse", publicName: "mobileNavOpenPulse", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, clickToOpen: { classPropertyName: "clickToOpen", publicName: "clickToOpen", isSignal: false, isRequired: false, transformFunction: null }, groupCollapsible: { classPropertyName: "groupCollapsible", publicName: "groupCollapsible", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, groupDefaultExpansion: { classPropertyName: "groupDefaultExpansion", publicName: "groupDefaultExpansion", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, viewQueries: [{ propertyName: "menuList", first: true, predicate: MenuListComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<nav class=\"app-sidebar app-nav-surface\" [class.app-sidebar--collapsed]=\"collapsed\"\r\n [attr.aria-label]=\"'Navega\u00E7\u00E3o principal'\">\r\n <!-- Cabe\u00E7alho fixo; pesquisa fixa em `.menu-list__toolbar`; barra s\u00F3 em `.menu-list__viewport`. -->\r\n <div class=\"app-sidebar__head\" data-app-sidebar-head=\"\" translate=\"no\">\r\n <div class=\"app-sidebar__brand\"><ng-content select=\"[appSidebarBrand]\" /></div>\r\n <div class=\"app-sidebar__toolbar\"><ng-content select=\"[appSidebarToolbar]\" /></div>\r\n </div>\r\n <div class=\"app-sidebar__scroll\">\r\n <app-menu-list\r\n class=\"app-sidebar__list\"\r\n [appTheme]=\"appTheme()\"\r\n [items]=\"items\"\r\n [menuId]=\"menuId\"\r\n [dense]=\"collapsed\"\r\n [compressText]=\"listCompressText()\"\r\n [searchable]=\"searchable\"\r\n [clickToOpen]=\"clickToOpen\"\r\n [groupCollapsible]=\"groupCollapsible\"\r\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\r\n [selectedItemId]=\"selectedItemId\"\r\n (itemSelect)=\"onSidebarItemSelect($event)\"\r\n (groupToggled)=\"onMenuGroupToggled($event)\"\r\n (selectionScrollHint)=\"scheduleScrollToSelected()\"\r\n />\r\n </div>\r\n</nav>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;flex:1 1 auto;align-self:stretch;min-width:0;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.app-sidebar{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;padding:.65rem .35rem .65rem .5rem;background:var(--app-color-nav-shell-bg);border-right:1px solid var(--app-color-nav-border-subtle)}.app-sidebar--collapsed{padding-inline:.425rem}.app-sidebar__head[data-app-sidebar-head]{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.35rem;width:100%;min-height:2.35rem;background:var(--app-color-nav-shell-bg);padding:0 .1rem .45rem;padding-inline-start:.85rem!important;padding-inline-end:calc(.1rem + 4px)!important;box-sizing:border-box;direction:ltr;unicode-bidi:isolate;flex-direction:row!important;justify-content:flex-start!important;direction:ltr!important}.app-sidebar--collapsed .app-sidebar__head[data-app-sidebar-head]{justify-content:center!important;padding-inline-start:0!important;padding-inline-end:4px!important;gap:0}.app-sidebar__brand{order:0;flex:1 1 0%;min-width:0;align-self:center;display:flex;justify-content:flex-start;align-items:center;padding:0;box-sizing:border-box;font-size:.95rem;font-weight:700;line-height:1.25;color:var(--app-color-text-primary, #1a2f45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start!important}.app-sidebar__brand>*{text-align:inherit!important;margin-inline:0!important;margin-inline-start:0!important;margin-inline-end:0!important;padding-inline-start:0!important;padding-inline-end:0!important;box-sizing:border-box;min-width:0;align-self:center;max-width:100%}.app-sidebar__brand ::ng-deep [appSidebarBrand]{display:inline-flex!important;flex-direction:row!important;justify-content:flex-start!important;align-items:center!important;align-self:center!important;margin-inline-start:0!important;margin-inline-end:auto!important;margin-left:0!important;margin-right:auto!important;text-align:start!important;width:auto!important;max-width:100%!important;min-width:0!important;flex:1 1 0%!important;box-sizing:border-box}.app-sidebar__brand:empty{display:none}.app-sidebar--collapsed .app-sidebar__brand:not(:empty){display:none}.app-sidebar__toolbar{order:1;flex:0 0 auto;flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;align-self:stretch;min-width:0;padding:0;box-sizing:border-box;margin-inline-start:auto!important}.app-sidebar__toolbar:empty{display:none}.app-sidebar--collapsed .app-sidebar__toolbar:not(:empty){flex:1 1 auto!important;width:100%!important;min-width:0!important;margin-inline-start:0!important;justify-content:center!important}.app-sidebar--collapsed .app-sidebar__toolbar ::ng-deep [appSidebarToolbar]:not(app-shell-sidebar-toggle)>:not(app-shell-sidebar-toggle){display:none!important}.app-sidebar__scroll{flex:1 1 auto;min-height:0;overflow:hidden;display:flex;flex-direction:column}.app-sidebar__list{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box}@media(min-width:52.0625rem){.app-sidebar .app-sidebar__head[data-app-sidebar-head]{padding-top:.2rem}.app-sidebar .app-sidebar__brand ::ng-deep [appSidebarBrand]{min-height:2.35rem!important;height:2.35rem!important;line-height:1!important}}:host-context(.app-drawer__body) .app-sidebar__head[data-app-sidebar-head]{justify-content:flex-start!important;align-items:center!important;padding-top:0!important;padding-bottom:.35rem!important;z-index:1!important}:host-context(.app-drawer__body) .app-sidebar__brand{justify-content:flex-start!important;flex:1 1 0%!important;min-width:0!important;text-align:start!important}:host-context(.app-drawer__body) .app-sidebar__toolbar:not(:empty){margin-inline-start:auto!important;justify-content:flex-end!important;align-self:stretch!important}:host-context(.app-drawer__body) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;min-height:auto!important;height:auto!important;line-height:1.25!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__label{padding-top:.72rem!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__icon{transform:translateY(.1875rem)}:host-context(.app-shell__sidebar) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;text-align:start!important}\n"], dependencies: [{ kind: "component", type: MenuListComponent, selector: "app-menu-list", inputs: ["appTheme", "items", "menuId", "dense", "nested", "selectedItemId", "compressText", "clickToOpen", "groupCollapsible", "groupDefaultExpansion", "persistGroupExpansion", "searchable", "searchPlaceholder"], outputs: ["itemSelect", "closeRequest", "submenuBack", "groupToggled", "selectionScrollHint"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11500
11789
  }
11501
11790
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AppSidebarComponent, decorators: [{
11502
11791
  type: Component,
11503
- args: [{ selector: 'app-sidebar', imports: [MenuListComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"app-sidebar app-nav-surface\" [class.app-sidebar--collapsed]=\"collapsed\"\r\n [attr.aria-label]=\"'Navega\u00E7\u00E3o principal'\">\r\n <!-- Cabe\u00E7alho fixo; pesquisa fixa em `.menu-list__toolbar`; barra s\u00F3 em `.menu-list__viewport`. -->\r\n <div class=\"app-sidebar__head\" data-app-sidebar-head=\"\" translate=\"no\">\r\n <div class=\"app-sidebar__brand\"><ng-content select=\"[appSidebarBrand]\" /></div>\r\n <div class=\"app-sidebar__toolbar\"><ng-content select=\"[appSidebarToolbar]\" /></div>\r\n </div>\r\n <div class=\"app-sidebar__scroll\">\r\n <app-menu-list\r\n class=\"app-sidebar__list\"\r\n [appTheme]=\"appTheme()\"\r\n [items]=\"items\"\r\n [menuId]=\"menuId\"\r\n [dense]=\"collapsed\"\r\n [compressText]=\"listCompressText()\"\r\n [searchable]=\"searchable\"\r\n [clickToOpen]=\"clickToOpen\"\r\n [groupCollapsible]=\"groupCollapsible\"\r\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\r\n [selectedItemId]=\"selectedItemId\"\r\n (itemSelect)=\"itemSelect.emit($event)\"\r\n (groupToggled)=\"onMenuGroupToggled($event)\"\r\n />\r\n </div>\r\n</nav>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;flex:1 1 auto;align-self:stretch;min-width:0;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.app-sidebar{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;padding:.65rem .35rem .65rem .5rem;background:var(--app-color-nav-shell-bg);border-right:1px solid var(--app-color-nav-border-subtle)}.app-sidebar--collapsed{padding-inline:.425rem}.app-sidebar__head[data-app-sidebar-head]{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.35rem;width:100%;min-height:2.35rem;background:var(--app-color-nav-shell-bg);padding:0 .1rem .45rem;padding-inline-start:.85rem!important;padding-inline-end:calc(.1rem + 4px)!important;box-sizing:border-box;direction:ltr;unicode-bidi:isolate;flex-direction:row!important;justify-content:flex-start!important;direction:ltr!important}.app-sidebar--collapsed .app-sidebar__head[data-app-sidebar-head]{justify-content:center!important;padding-inline-start:0!important;padding-inline-end:4px!important;gap:0}.app-sidebar__brand{order:0;flex:1 1 0%;min-width:0;align-self:center;display:flex;justify-content:flex-start;align-items:center;padding:0;box-sizing:border-box;font-size:.95rem;font-weight:700;line-height:1.25;color:var(--app-color-text-primary, #1a2f45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start!important}.app-sidebar__brand>*{text-align:inherit!important;margin-inline:0!important;margin-inline-start:0!important;margin-inline-end:0!important;padding-inline-start:0!important;padding-inline-end:0!important;box-sizing:border-box;min-width:0;align-self:center;max-width:100%}.app-sidebar__brand ::ng-deep [appSidebarBrand]{display:inline-flex!important;flex-direction:row!important;justify-content:flex-start!important;align-items:center!important;align-self:center!important;margin-inline-start:0!important;margin-inline-end:auto!important;margin-left:0!important;margin-right:auto!important;text-align:start!important;width:auto!important;max-width:100%!important;min-width:0!important;flex:1 1 0%!important;box-sizing:border-box}.app-sidebar__brand:empty{display:none}.app-sidebar--collapsed .app-sidebar__brand:not(:empty){display:none}.app-sidebar__toolbar{order:1;flex:0 0 auto;flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;align-self:stretch;min-width:0;padding:0;box-sizing:border-box;margin-inline-start:auto!important}.app-sidebar__toolbar:empty{display:none}.app-sidebar--collapsed .app-sidebar__toolbar:not(:empty){flex:1 1 auto!important;width:100%!important;min-width:0!important;margin-inline-start:0!important;justify-content:center!important}.app-sidebar--collapsed .app-sidebar__toolbar ::ng-deep [appSidebarToolbar]:not(app-shell-sidebar-toggle)>:not(app-shell-sidebar-toggle){display:none!important}.app-sidebar__scroll{flex:1 1 auto;min-height:0;overflow:hidden;display:flex;flex-direction:column}.app-sidebar__list{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box}@media(min-width:52.0625rem){.app-sidebar .app-sidebar__head[data-app-sidebar-head]{padding-top:.2rem}.app-sidebar .app-sidebar__brand ::ng-deep [appSidebarBrand]{min-height:2.35rem!important;height:2.35rem!important;line-height:1!important}}:host-context(.app-drawer__body) .app-sidebar__head[data-app-sidebar-head]{justify-content:flex-start!important;align-items:center!important;padding-top:0!important;padding-bottom:.35rem!important;z-index:1!important}:host-context(.app-drawer__body) .app-sidebar__brand{justify-content:flex-start!important;flex:1 1 0%!important;min-width:0!important;text-align:start!important}:host-context(.app-drawer__body) .app-sidebar__toolbar:not(:empty){margin-inline-start:auto!important;justify-content:flex-end!important;align-self:stretch!important}:host-context(.app-drawer__body) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;min-height:auto!important;height:auto!important;line-height:1.25!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__label{padding-top:.72rem!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__icon{transform:translateY(.1875rem)}:host-context(.app-shell__sidebar) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;text-align:start!important}\n"] }]
11792
+ args: [{ selector: 'app-sidebar', imports: [MenuListComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"app-sidebar app-nav-surface\" [class.app-sidebar--collapsed]=\"collapsed\"\r\n [attr.aria-label]=\"'Navega\u00E7\u00E3o principal'\">\r\n <!-- Cabe\u00E7alho fixo; pesquisa fixa em `.menu-list__toolbar`; barra s\u00F3 em `.menu-list__viewport`. -->\r\n <div class=\"app-sidebar__head\" data-app-sidebar-head=\"\" translate=\"no\">\r\n <div class=\"app-sidebar__brand\"><ng-content select=\"[appSidebarBrand]\" /></div>\r\n <div class=\"app-sidebar__toolbar\"><ng-content select=\"[appSidebarToolbar]\" /></div>\r\n </div>\r\n <div class=\"app-sidebar__scroll\">\r\n <app-menu-list\r\n class=\"app-sidebar__list\"\r\n [appTheme]=\"appTheme()\"\r\n [items]=\"items\"\r\n [menuId]=\"menuId\"\r\n [dense]=\"collapsed\"\r\n [compressText]=\"listCompressText()\"\r\n [searchable]=\"searchable\"\r\n [clickToOpen]=\"clickToOpen\"\r\n [groupCollapsible]=\"groupCollapsible\"\r\n [groupDefaultExpansion]=\"groupDefaultExpansion\"\r\n [selectedItemId]=\"selectedItemId\"\r\n (itemSelect)=\"onSidebarItemSelect($event)\"\r\n (groupToggled)=\"onMenuGroupToggled($event)\"\r\n (selectionScrollHint)=\"scheduleScrollToSelected()\"\r\n />\r\n </div>\r\n</nav>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;flex:1 1 auto;align-self:stretch;min-width:0;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.app-sidebar{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;box-sizing:border-box;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;padding:.65rem .35rem .65rem .5rem;background:var(--app-color-nav-shell-bg);border-right:1px solid var(--app-color-nav-border-subtle)}.app-sidebar--collapsed{padding-inline:.425rem}.app-sidebar__head[data-app-sidebar-head]{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.35rem;width:100%;min-height:2.35rem;background:var(--app-color-nav-shell-bg);padding:0 .1rem .45rem;padding-inline-start:.85rem!important;padding-inline-end:calc(.1rem + 4px)!important;box-sizing:border-box;direction:ltr;unicode-bidi:isolate;flex-direction:row!important;justify-content:flex-start!important;direction:ltr!important}.app-sidebar--collapsed .app-sidebar__head[data-app-sidebar-head]{justify-content:center!important;padding-inline-start:0!important;padding-inline-end:4px!important;gap:0}.app-sidebar__brand{order:0;flex:1 1 0%;min-width:0;align-self:center;display:flex;justify-content:flex-start;align-items:center;padding:0;box-sizing:border-box;font-size:.95rem;font-weight:700;line-height:1.25;color:var(--app-color-text-primary, #1a2f45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start!important}.app-sidebar__brand>*{text-align:inherit!important;margin-inline:0!important;margin-inline-start:0!important;margin-inline-end:0!important;padding-inline-start:0!important;padding-inline-end:0!important;box-sizing:border-box;min-width:0;align-self:center;max-width:100%}.app-sidebar__brand ::ng-deep [appSidebarBrand]{display:inline-flex!important;flex-direction:row!important;justify-content:flex-start!important;align-items:center!important;align-self:center!important;margin-inline-start:0!important;margin-inline-end:auto!important;margin-left:0!important;margin-right:auto!important;text-align:start!important;width:auto!important;max-width:100%!important;min-width:0!important;flex:1 1 0%!important;box-sizing:border-box}.app-sidebar__brand:empty{display:none}.app-sidebar--collapsed .app-sidebar__brand:not(:empty){display:none}.app-sidebar__toolbar{order:1;flex:0 0 auto;flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;align-self:stretch;min-width:0;padding:0;box-sizing:border-box;margin-inline-start:auto!important}.app-sidebar__toolbar:empty{display:none}.app-sidebar--collapsed .app-sidebar__toolbar:not(:empty){flex:1 1 auto!important;width:100%!important;min-width:0!important;margin-inline-start:0!important;justify-content:center!important}.app-sidebar--collapsed .app-sidebar__toolbar ::ng-deep [appSidebarToolbar]:not(app-shell-sidebar-toggle)>:not(app-shell-sidebar-toggle){display:none!important}.app-sidebar__scroll{flex:1 1 auto;min-height:0;overflow:hidden;display:flex;flex-direction:column}.app-sidebar__list{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box}@media(min-width:52.0625rem){.app-sidebar .app-sidebar__head[data-app-sidebar-head]{padding-top:.2rem}.app-sidebar .app-sidebar__brand ::ng-deep [appSidebarBrand]{min-height:2.35rem!important;height:2.35rem!important;line-height:1!important}}:host-context(.app-drawer__body) .app-sidebar__head[data-app-sidebar-head]{justify-content:flex-start!important;align-items:center!important;padding-top:0!important;padding-bottom:.35rem!important;z-index:1!important}:host-context(.app-drawer__body) .app-sidebar__brand{justify-content:flex-start!important;flex:1 1 0%!important;min-width:0!important;text-align:start!important}:host-context(.app-drawer__body) .app-sidebar__toolbar:not(:empty){margin-inline-start:auto!important;justify-content:flex-end!important;align-self:stretch!important}:host-context(.app-drawer__body) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;min-height:auto!important;height:auto!important;line-height:1.25!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__label{padding-top:.72rem!important}:host-context(.app-drawer__body) ::ng-deep app-menu-list .menu-list__icon{transform:translateY(.1875rem)}:host-context(.app-shell__sidebar) .app-sidebar__brand ::ng-deep [appSidebarBrand]{justify-content:flex-start!important;margin-inline-start:0!important;margin-inline-end:auto!important;text-align:start!important}\n"] }]
11504
11793
  }], ctorParameters: () => [], propDecorators: { appTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTheme", required: false }] }], items: [{
11505
11794
  type: Input,
11506
11795
  args: [{ required: true }]
@@ -11511,6 +11800,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
11511
11800
  }], collapsed: [{
11512
11801
  type: Input,
11513
11802
  args: [{ transform: booleanAttribute }]
11803
+ }], mobileNavOpenPulse: [{
11804
+ type: Input,
11805
+ args: [{ transform: booleanAttribute }]
11514
11806
  }], searchable: [{
11515
11807
  type: Input,
11516
11808
  args: [{ transform: booleanAttribute }]
@@ -11523,6 +11815,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
11523
11815
  type: Input
11524
11816
  }], itemSelect: [{
11525
11817
  type: Output
11818
+ }], menuList: [{
11819
+ type: ViewChild,
11820
+ args: [MenuListComponent]
11526
11821
  }] } });
11527
11822
 
11528
11823
  /**