structra-ui 0.2.31 → 0.2.32

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.
@@ -173,6 +173,11 @@ interface MenuItemGroup<T = string> {
173
173
  label?: string;
174
174
  /** Itens e submenus aninhados dentro do grupo. */
175
175
  items: readonly MenuNodeItem<T>[];
176
+ /**
177
+ * Se `true`, o grupo não recolhe e não mostra controlo de expandir — útil para a secção principal
178
+ * em relação a grupos secundários colapsáveis.
179
+ */
180
+ alwaysExpanded?: boolean;
176
181
  }
177
182
  /** Folha: ação ou divisor. */
178
183
  type MenuLeafItem<T = string> = MenuItemAction<T> | MenuItemDivider;
@@ -3061,18 +3066,25 @@ interface MenuRowAction<T = string> {
3061
3066
  item: MenuItemAction<T>;
3062
3067
  /** Índice na navegação por teclado; `null` se desabilitado. */
3063
3068
  focusIndex: number | null;
3069
+ /** `null` = fora de grupo; caso contrário, pertence a este grupo (oculto se o grupo estiver fechado). */
3070
+ containingGroupId?: number | null;
3064
3071
  }
3065
3072
  interface MenuRowDivider {
3066
3073
  kind: 'divider';
3074
+ containingGroupId?: number | null;
3067
3075
  }
3068
3076
  interface MenuRowGroup {
3069
3077
  kind: 'group';
3070
3078
  label?: string;
3079
+ groupId: number;
3080
+ /** Eco de {@link MenuItemGroup.alwaysExpanded}. */
3081
+ alwaysExpanded?: boolean;
3071
3082
  }
3072
3083
  interface MenuRowSubmenu<T = string> {
3073
3084
  kind: 'submenu';
3074
3085
  item: MenuItemSubmenu<T>;
3075
3086
  focusIndex: number | null;
3087
+ containingGroupId?: number | null;
3076
3088
  }
3077
3089
  type MenuRow<T = string> = MenuRowAction<T> | MenuRowDivider | MenuRowGroup | MenuRowSubmenu<T>;
3078
3090
 
@@ -3103,11 +3115,25 @@ declare class MenuListComponent<T = string> implements OnChanges {
3103
3115
  * - **`false`** — igual ao comportamento anterior: abre **só com hover** (com atraso), sem alternar ao clicar na linha.
3104
3116
  */
3105
3117
  clickToOpen: boolean;
3118
+ /**
3119
+ * Grupos (`kind: 'group'`): quando `false`, cabeçalhos sem seta e itens sempre visíveis (não recolhe).
3120
+ */
3121
+ groupCollapsible: boolean;
3122
+ /**
3123
+ * Com {@link groupCollapsible}: estado inicial ao receber `items`.
3124
+ * - `'all'` — todos os grupos expandidos (omissão).
3125
+ * - `'first'` — só o primeiro grupo expandível fica aberto; os restantes recolhidos.
3126
+ */
3127
+ groupDefaultExpansion: 'all' | 'first';
3106
3128
  readonly itemSelect: EventEmitter<T>;
3107
3129
  readonly closeRequest: EventEmitter<void>;
3108
3130
  readonly submenuBack: EventEmitter<void>;
3109
3131
  private nestedLists?;
3110
3132
  rows: MenuRow<T>[];
3133
+ /** Filtrado + índices de foco coerentes com grupos recolhidos. */
3134
+ displayRows: MenuRow<T>[];
3135
+ /** Ids de grupo expandidos; ao mudar `items`, todos voltam a abertos. */
3136
+ private readonly expandedGroupIds;
3111
3137
  private focusableCount;
3112
3138
  /** Índice entre `0` e `focusableCount - 1`, ou `-1` = nenhum realce. */
3113
3139
  activeIndex: number;
@@ -3121,11 +3147,26 @@ declare class MenuListComponent<T = string> implements OnChanges {
3121
3147
  }>;
3122
3148
  overlayPanelClasses(): string[];
3123
3149
  onNestedItemSelect(id: T): void;
3150
+ /** Identidade estável para `@for` — `track $index` quebra quando linhas são omitidas por grupo recolhido. */
3151
+ trackDisplayRow(index: number, row: MenuRow<T>): string;
3124
3152
  ngOnChanges(changes: SimpleChanges): void;
3153
+ /** Estado inicial de grupos expandidos (chaveado por {@link groupDefaultExpansion}). */
3154
+ private applyInitialExpandedGroups;
3155
+ private syncDisplayRows;
3156
+ isGroupExpanded(groupId: number): boolean;
3157
+ /** Eco de `MenuItemGroup.alwaysExpanded` para este `groupId`. */
3158
+ private isGroupAlwaysExpanded;
3159
+ private isRowVisible;
3160
+ toggleGroup(groupId: number): void;
3125
3161
  submenuRowKey(row: MenuRow<T>, index: number): string;
3126
3162
  isSubmenuOpen(row: MenuRow<T>, index: number): boolean;
3127
3163
  submenuMenuId(row: MenuRow<T>): string;
3128
3164
  onRowMouseEnter(row: MenuRow<T>): void;
3165
+ /**
3166
+ * Grupo / divisor não são `menuitem` com foco-mãe — ao passar o rato para o cabeçalho do grupo,
3167
+ * limpa o realce da opção anterior (`.menu-list__option--active`).
3168
+ */
3169
+ onNonOptionSurfaceEnter(): void;
3129
3170
  onSubmenuTriggerEnter(row: MenuRow<T>, index: number): void;
3130
3171
  onSubmenuTriggerLeave(_row: MenuRow<T>, index: number): void;
3131
3172
  onSubmenuPanelEnter(): void;
@@ -3151,10 +3192,11 @@ declare class MenuListComponent<T = string> implements OnChanges {
3151
3192
  private focusActiveDom;
3152
3193
  onKeydown(ev: KeyboardEvent): void;
3153
3194
  static ɵfac: i0.ɵɵFactoryDeclaration<MenuListComponent<any>, never>;
3154
- static ɵcmp: i0.ɵɵComponentDeclaration<MenuListComponent<any>, "app-menu-list", never, { "appTheme": { "alias": "appTheme"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; }; "menuId": { "alias": "menuId"; "required": false; }; "dense": { "alias": "dense"; "required": false; }; "nested": { "alias": "nested"; "required": false; }; "selectedItemId": { "alias": "selectedItemId"; "required": false; }; "compressText": { "alias": "compressText"; "required": false; }; "clickToOpen": { "alias": "clickToOpen"; "required": false; }; }, { "itemSelect": "itemSelect"; "closeRequest": "closeRequest"; "submenuBack": "submenuBack"; }, never, never, true, [{ directive: typeof i1.CdkScrollable; inputs: {}; outputs: {}; }]>;
3195
+ static ɵcmp: i0.ɵɵComponentDeclaration<MenuListComponent<any>, "app-menu-list", never, { "appTheme": { "alias": "appTheme"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; }; "menuId": { "alias": "menuId"; "required": false; }; "dense": { "alias": "dense"; "required": false; }; "nested": { "alias": "nested"; "required": false; }; "selectedItemId": { "alias": "selectedItemId"; "required": false; }; "compressText": { "alias": "compressText"; "required": false; }; "clickToOpen": { "alias": "clickToOpen"; "required": false; }; "groupCollapsible": { "alias": "groupCollapsible"; "required": false; }; "groupDefaultExpansion": { "alias": "groupDefaultExpansion"; "required": false; }; }, { "itemSelect": "itemSelect"; "closeRequest": "closeRequest"; "submenuBack": "submenuBack"; }, never, never, true, [{ directive: typeof i1.CdkScrollable; inputs: {}; outputs: {}; }]>;
3155
3196
  static ngAcceptInputType_dense: unknown;
3156
3197
  static ngAcceptInputType_nested: unknown;
3157
3198
  static ngAcceptInputType_compressText: unknown;
3199
+ static ngAcceptInputType_groupCollapsible: unknown;
3158
3200
  }
3159
3201
 
3160
3202
  /**
@@ -3194,9 +3236,15 @@ declare class MenuGroupComponent {
3194
3236
  label?: string;
3195
3237
  /** Quando `true`, não mostra o título (ex.: sidebar colapsada só com ícones). */
3196
3238
  hideLabel: boolean;
3239
+ /** Quando `true`, mostra seta e permite expandir/recolher (controlado pelo `menu-list`). */
3240
+ collapsible: boolean;
3241
+ expanded: boolean;
3242
+ readonly toggleExpand: EventEmitter<void>;
3197
3243
  static ɵfac: i0.ɵɵFactoryDeclaration<MenuGroupComponent, never>;
3198
- static ɵcmp: i0.ɵɵComponentDeclaration<MenuGroupComponent, "app-menu-group", never, { "label": { "alias": "label"; "required": false; }; "hideLabel": { "alias": "hideLabel"; "required": false; }; }, {}, never, never, true, never>;
3244
+ static ɵcmp: i0.ɵɵComponentDeclaration<MenuGroupComponent, "app-menu-group", never, { "label": { "alias": "label"; "required": false; }; "hideLabel": { "alias": "hideLabel"; "required": false; }; "collapsible": { "alias": "collapsible"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "toggleExpand": "toggleExpand"; }, never, never, true, never>;
3199
3245
  static ngAcceptInputType_hideLabel: unknown;
3246
+ static ngAcceptInputType_collapsible: unknown;
3247
+ static ngAcceptInputType_expanded: unknown;
3200
3248
  }
3201
3249
 
3202
3250
  /**
@@ -3459,6 +3507,15 @@ declare class AppSidebarComponent<T extends string = string> implements OnChange
3459
3507
  * ou por **hover** (`false`).
3460
3508
  */
3461
3509
  clickToOpen: boolean;
3510
+ /**
3511
+ * Repassado a {@link MenuListComponent.groupCollapsible}: `false` desactiva expandir/recolher nas secções.
3512
+ */
3513
+ groupCollapsible: boolean;
3514
+ /**
3515
+ * Repassado a {@link MenuListComponent.groupDefaultExpansion}: estado inicial dos grupos ao carregar `items`.
3516
+ * Com `'first'` e um primeiro grupo `alwaysExpanded`, os restantes grupos colapsáveis começam fechados.
3517
+ */
3518
+ groupDefaultExpansion: 'all' | 'first';
3462
3519
  readonly itemSelect: EventEmitter<T>;
3463
3520
  /**
3464
3521
  * Valor efectivo de `compressText` em `app-menu-list`: ao expandir, mantém-se comprimido
@@ -3473,8 +3530,9 @@ declare class AppSidebarComponent<T extends string = string> implements OnChange
3473
3530
  private scheduleSidebarHeadLayoutGuards;
3474
3531
  private applySidebarHeadLayoutGuards;
3475
3532
  static ɵfac: i0.ɵɵFactoryDeclaration<AppSidebarComponent<any>, never>;
3476
- static ɵcmp: i0.ɵɵComponentDeclaration<AppSidebarComponent<any>, "app-sidebar", never, { "appTheme": { "alias": "appTheme"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; }; "menuId": { "alias": "menuId"; "required": false; }; "selectedItemId": { "alias": "selectedItemId"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "clickToOpen": { "alias": "clickToOpen"; "required": false; }; }, { "itemSelect": "itemSelect"; }, never, ["[appSidebarBrand]", "[appSidebarToolbar]"], true, never>;
3533
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppSidebarComponent<any>, "app-sidebar", never, { "appTheme": { "alias": "appTheme"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; }; "menuId": { "alias": "menuId"; "required": false; }; "selectedItemId": { "alias": "selectedItemId"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "clickToOpen": { "alias": "clickToOpen"; "required": false; }; "groupCollapsible": { "alias": "groupCollapsible"; "required": false; }; "groupDefaultExpansion": { "alias": "groupDefaultExpansion"; "required": false; }; }, { "itemSelect": "itemSelect"; }, never, ["[appSidebarBrand]", "[appSidebarToolbar]"], true, never>;
3477
3534
  static ngAcceptInputType_collapsed: unknown;
3535
+ static ngAcceptInputType_groupCollapsible: unknown;
3478
3536
  }
3479
3537
 
3480
3538
  /**