Files
ui-essentials/projects/demo-ui-essentials/src/app/features/dashboard/dashboard.sidebar.component.ts
skyai_dev 2bbbf1b9f1 Add comprehensive UI component expansion
- Add new components: enhanced-table, fab-menu, icon-button, snackbar, select, tag-input, bottom-navigation, stepper, command-palette, floating-toolbar, transfer-list
- Refactor table-actions and select components
- Update component styles and exports
- Add corresponding demo components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 21:50:45 +10:00

158 lines
4.2 KiB
TypeScript

import { Component, EventEmitter, Output, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
MenuContainerComponent,
MenuSubmenuComponent,
MenuItemComponent,
MenuItemData
} from '../../../../../ui-essentials/src/lib/components/navigation/menu';
export interface SidebarMenuItem extends MenuItemData {
children?: SidebarMenuItem[];
expanded?: boolean;
isParent?: boolean;
}
@Component({
selector: 'skyui-dashboard-sidebar',
standalone: true,
imports: [
CommonModule,
MenuContainerComponent,
MenuSubmenuComponent,
MenuItemComponent
],
template: `
<ui-menu-container
[elevation]="'none'"
[spacing]="'none'"
[rounded]="false"
class="sidebar-container"
>
@for(item of data; track item.id) {
@if(item.isParent && item.children) {
<ui-menu-submenu
[parentItem]="getMenuItemData(item)"
[size]="'md'"
[iconPosition]="'left'"
[isOpen]="item.expanded || false"
[submenuElevation]="'none'"
[submenuSpacing]="'xs'"
(submenuToggled)="onSubmenuToggled($event)"
(parentItemClick)="handleMenuClick($event.id || '')"
>
@for(child of item.children; track child.id) {
<ui-menu-item
[data]="getMenuItemData(child)"
[size]="'sm'"
[iconPosition]="'left'"
[indent]="true"
(itemClick)="handleMenuClick($event.id || '')"
/>
}
</ui-menu-submenu>
} @else {
<ui-menu-item
[data]="getMenuItemData(item)"
[size]="'md'"
[iconPosition]="'left'"
(itemClick)="handleMenuClick($event.id || '')"
/>
}
}
</ui-menu-container>
`,
styleUrls: ['./dashboard.sidebar.component.scss']
})
export class DashboardSidebarComponent implements OnInit {
@Input() data: SidebarMenuItem[] = [];
@Input() set active(value: string) { this.setActive(value) }
@Output() selected = new EventEmitter<string>();
handleMenuClick(id: string): void {
this.setActive(id);
this.selected.emit(id);
}
setActive(id: string): void {
this.setActiveRecursive(this.data, id);
}
private setActiveRecursive(items: SidebarMenuItem[], id: string): void {
items.forEach(item => {
item.active = item.id === id;
if (item.children) {
this.setActiveRecursive(item.children, id);
}
});
}
getActiveMenuItem(): SidebarMenuItem | undefined {
return this.getActiveMenuItemRecursive(this.data);
}
private getActiveMenuItemRecursive(items: SidebarMenuItem[]): SidebarMenuItem | undefined {
for (const item of items) {
if (item.active) return item;
if (item.children) {
const found = this.getActiveMenuItemRecursive(item.children);
if (found) return found;
}
}
return undefined;
}
clearSelection(): void {
this.clearSelectionRecursive(this.data);
}
private clearSelectionRecursive(items: SidebarMenuItem[]): void {
items.forEach(item => {
item.active = false;
if (item.children) {
this.clearSelectionRecursive(item.children);
}
});
}
toggleExpanded(item: SidebarMenuItem): void {
if (item.isParent) {
item.expanded = !item.expanded;
}
}
getMenuItemData(item: SidebarMenuItem): MenuItemData {
return {
id: item.id,
label: item.label,
icon: item.icon,
active: item.active,
hasSubmenu: item.isParent && !!item.children,
disabled: item.disabled
};
}
onSubmenuToggled(event: { item: MenuItemData; isOpen: boolean }): void {
const sidebarItem = this.findItemById(this.data, event.item.id || '');
if (sidebarItem && sidebarItem.isParent) {
sidebarItem.expanded = event.isOpen;
}
}
private findItemById(items: SidebarMenuItem[], id: string): SidebarMenuItem | undefined {
for (const item of items) {
if (item.id === id) return item;
if (item.children) {
const found = this.findItemById(item.children, id);
if (found) return found;
}
}
return undefined;
}
ngOnInit(): void {
}
}