@elavarasanbititude/ng-cwr-sidebar 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,9 @@ import { Injectable, EventEmitter, inject, Output, Input, ChangeDetectionStrateg
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2 from '@angular/router';
6
- import { RouterModule } from '@angular/router';
6
+ import { Router, NavigationEnd, RouterModule } from '@angular/router';
7
7
  import { BehaviorSubject } from 'rxjs';
8
+ import { filter } from 'rxjs/operators';
8
9
 
9
10
  class SidebarService {
10
11
  collapsedSubject = new BehaviorSubject(false);
@@ -83,37 +84,56 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
83
84
  class Sidebar {
84
85
  menuItems = [];
85
86
  config = {};
87
+ collapsed = false;
88
+ logoUrl;
89
+ logoAlt = 'Logo';
90
+ showToggle = true;
86
91
  menuItemClicked = new EventEmitter();
87
92
  collapsedChange = new EventEmitter();
93
+ itemBadgeClick = new EventEmitter();
88
94
  sidebarService = inject(SidebarService);
95
+ router = inject(Router);
89
96
  get collapsed$() {
90
97
  return this.sidebarService.collapsed$;
91
98
  }
92
99
  expandedItems = new Set();
100
+ isCollapsed = false;
93
101
  defaultConfig = {
94
102
  collapsed: false,
95
103
  position: 'left',
96
- width: '250px',
104
+ width: '240px',
97
105
  collapsedWidth: '60px',
98
- backgroundColor: '#f5f5f5',
99
- textColor: '#333',
100
- hoverColor: '#e0e0e0',
106
+ backgroundColor: '#141F2D',
107
+ textColor: '#3A4D63',
108
+ hoverColor: '#FDFDFD',
101
109
  toggleButton: true,
102
110
  overlayOnMobile: true,
103
111
  };
104
112
  ngOnInit() {
113
+ this.isCollapsed = this.collapsed;
105
114
  this.sidebarService.setMenuItems(this.menuItems);
106
115
  const mergedConfig = { ...this.defaultConfig, ...this.config };
107
116
  this.sidebarService.setConfig(mergedConfig);
117
+ // Track router navigation for active state
118
+ this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
119
+ // Trigger change detection for route changes
120
+ });
108
121
  }
109
- ngOnChanges() {
110
- if (this.menuItems.length > 0) {
122
+ ngOnChanges(changes) {
123
+ if (changes['menuItems'] && !changes['menuItems'].firstChange) {
111
124
  this.sidebarService.setMenuItems(this.menuItems);
112
125
  }
126
+ if (changes['collapsed']) {
127
+ this.isCollapsed = this.collapsed;
128
+ }
129
+ if (changes['config'] && !changes['config'].firstChange) {
130
+ this.sidebarService.setConfig({ ...this.defaultConfig, ...this.config });
131
+ }
113
132
  }
114
133
  toggleSidebar() {
134
+ this.isCollapsed = !this.isCollapsed;
115
135
  this.sidebarService.toggleCollapsed();
116
- this.collapsedChange.emit(this.sidebarService.getCollapsed());
136
+ this.collapsedChange.emit(this.isCollapsed);
117
137
  }
118
138
  toggleExpand(item) {
119
139
  if (item.children && item.children.length > 0) {
@@ -136,26 +156,51 @@ class Sidebar {
136
156
  }
137
157
  this.menuItemClicked.emit(item);
138
158
  }
139
- hasCildren(item) {
159
+ onBadgeClick(event, item) {
160
+ event.stopPropagation();
161
+ this.itemBadgeClick.emit(item);
162
+ }
163
+ hasChildren(item) {
140
164
  return !!(item.children && item.children.length > 0);
141
165
  }
166
+ isActiveRoute(item) {
167
+ if (item.isActive) {
168
+ return item.isActive();
169
+ }
170
+ return item.route ? this.router.url.includes(`/${item.route}`) : false;
171
+ }
142
172
  getConfig() {
143
173
  return this.sidebarService.getConfig();
144
174
  }
175
+ closeSidebar() {
176
+ if (!this.isCollapsed) {
177
+ this.toggleSidebar();
178
+ }
179
+ }
145
180
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Sidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
146
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: Sidebar, isStandalone: true, selector: "cwr-sidebar", inputs: { menuItems: "menuItems", config: "config" }, outputs: { menuItemClicked: "menuItemClicked", collapsedChange: "collapsedChange" }, usesOnChanges: true, ngImport: i0, template: "<div \n class=\"cwr-sidebar\"\n [ngClass]=\"{ 'collapsed': (collapsed$ | async) }\"\n [style.width]=\"(collapsed$ | async) ? getConfig().collapsedWidth : getConfig().width\"\n [style.backgroundColor]=\"getConfig().backgroundColor\"\n [style.color]=\"getConfig().textColor\"\n>\n <!-- Toggle Button -->\n <div class=\"sidebar-header\" *ngIf=\"getConfig().toggleButton\">\n <button \n class=\"toggle-btn\" \n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"(collapsed$ | async) ? 'Expand sidebar' : 'Collapse sidebar'\"\n >\n <span class=\"toggle-icon\">\u2630</span>\n </button>\n <span class=\"header-title\" *ngIf=\"!(collapsed$ | async)\">Menu</span>\n </div>\n\n <!-- Menu Items -->\n <nav class=\"sidebar-nav\">\n <ul class=\"menu-list\">\n <li \n *ngFor=\"let item of menuItems\"\n class=\"menu-item\"\n [ngClass]=\"{ \n 'has-children': hasCildren(item),\n 'expanded': isExpanded(item),\n 'disabled': item.disabled\n }\"\n >\n <button \n class=\"menu-link\"\n [routerLink]=\"item.route\"\n (click)=\"onMenuItemClick(item)\"\n [disabled]=\"item.disabled\"\n >\n <span class=\"menu-icon\" *ngIf=\"item.icon\">{{ item.icon }}</span>\n <span class=\"menu-label\" *ngIf=\"!(collapsed$ | async)\">\n {{ item.label }}\n </span>\n <span \n class=\"menu-badge\"\n *ngIf=\"item.badge && !(collapsed$ | async)\"\n [ngStyle]=\"{ 'background-color': item.badge.color || '#ff6b6b' }\"\n >\n {{ item.badge.text }}\n </span>\n <span \n class=\"expand-icon\"\n *ngIf=\"hasCildren(item)\"\n (click)=\"toggleExpand(item)\"\n [ngClass]=\"{ 'expanded': isExpanded(item) }\"\n >\n \u25BE\n </span>\n </button>\n\n <!-- Nested Menu Items -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasCildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n class=\"submenu-item\"\n [ngClass]=\"{ 'disabled': child.disabled }\"\n >\n <button \n class=\"submenu-link\"\n [routerLink]=\"child.route\"\n (click)=\"onMenuItemClick(child)\"\n [disabled]=\"child.disabled\"\n >\n <span class=\"submenu-icon\" *ngIf=\"child.icon\">{{ child.icon }}</span>\n <span class=\"submenu-label\">{{ child.label }}</span>\n </button>\n </li>\n </ul>\n </li>\n </ul>\n </nav>\n</div>\n", styles: [".cwr-sidebar{display:flex;flex-direction:column;height:100vh;background-color:#f5f5f5;color:#333;border-right:1px solid #ddd;overflow:hidden;transition:width .3s ease-in-out;position:relative;z-index:1000}.cwr-sidebar.collapsed{width:60px}.cwr-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1rem;border-bottom:1px solid #ddd;background-color:#00000005}.cwr-sidebar .sidebar-header .toggle-btn{background:transparent;border:none;cursor:pointer;padding:.5rem;display:flex;align-items:center;justify-content:center;color:#333;font-size:1.2rem;transition:background-color .3s,color .3s;border-radius:4px}.cwr-sidebar .sidebar-header .toggle-btn:hover{background-color:#e0e0e0;color:#007bff}.cwr-sidebar .sidebar-header .toggle-btn:active{transform:scale(.95)}.cwr-sidebar .sidebar-header .toggle-btn .toggle-icon{display:block}.cwr-sidebar .sidebar-header .header-title{flex:1;margin-left:.5rem;font-weight:600;font-size:.95rem;text-transform:uppercase;letter-spacing:.5px}.cwr-sidebar .sidebar-nav{flex:1;overflow-y:auto;overflow-x:hidden;padding:.5rem 0}.cwr-sidebar .sidebar-nav::-webkit-scrollbar{width:6px}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-track{background:transparent}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-thumb{background:#ccc;border-radius:3px}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-thumb:hover{background:#999}.cwr-sidebar .menu-list{list-style:none;padding:0;margin:0}.cwr-sidebar .menu-item{position:relative;transition:background-color .3s}.cwr-sidebar .menu-item.disabled{opacity:.5;cursor:not-allowed}.cwr-sidebar .menu-item:hover>.menu-link{background-color:#e0e0e0}.cwr-sidebar .menu-link{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 1rem;background:transparent;border:none;color:inherit;cursor:pointer;font-size:.95rem;text-align:left;transition:background-color .3s,color .3s;position:relative}.cwr-sidebar .menu-link:hover:not(:disabled){color:#007bff}.cwr-sidebar .menu-link:disabled{cursor:not-allowed}.cwr-sidebar .menu-link:focus{outline:2px solid #007bff;outline-offset:-2px}.cwr-sidebar .menu-link .menu-icon{display:flex;align-items:center;justify-content:center;min-width:24px;font-size:1.1rem;margin-right:.75rem}.cwr-sidebar .menu-link .menu-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cwr-sidebar .menu-link .menu-badge{display:inline-block;padding:.25rem .5rem;border-radius:12px;font-size:.75rem;font-weight:600;color:#fff;margin:0 .5rem;white-space:nowrap}.cwr-sidebar .menu-link .expand-icon{display:flex;align-items:center;justify-content:center;margin-left:.5rem;font-size:.75rem;transition:transform .3s;cursor:pointer}.cwr-sidebar .menu-link .expand-icon.expanded{transform:rotate(180deg)}.cwr-sidebar .submenu-list{list-style:none;padding:0;margin:0;background-color:#0000000d;max-height:none;overflow:visible;animation:slideDown .3s ease-in-out}.cwr-sidebar .submenu-item{position:relative;transition:background-color .3s}.cwr-sidebar .submenu-item.disabled{opacity:.5;cursor:not-allowed}.cwr-sidebar .submenu-item:hover>.submenu-link{background-color:#00000014}.cwr-sidebar .submenu-link{display:flex;align-items:center;width:100%;padding:.6rem 1rem .6rem 3rem;background:transparent;border:none;color:inherit;cursor:pointer;font-size:.9rem;text-align:left;transition:background-color .3s,color .3s}.cwr-sidebar .submenu-link:hover:not(:disabled){color:#007bff;background-color:#00000014}.cwr-sidebar .submenu-link:disabled{cursor:not-allowed}.cwr-sidebar .submenu-link:focus{outline:2px solid #007bff;outline-offset:-2px}.cwr-sidebar .submenu-link .submenu-icon{display:flex;align-items:center;justify-content:center;min-width:20px;font-size:1rem;margin-right:.75rem}.cwr-sidebar .submenu-link .submenu-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.cwr-sidebar{position:absolute;left:0;top:0;bottom:0;box-shadow:0 2px 10px #0003}.cwr-sidebar.collapsed{transform:translate(-100%);width:250px}.cwr-sidebar .sidebar-nav{height:calc(100vh - 60px)}}.cwr-sidebar{--sidebar-color: #f5f5f5;--text-color: #333}.cwr-sidebar .menu-link,.cwr-sidebar .submenu-link{color:var(--text-color)}.cwr-sidebar .menu-link:hover:not(:disabled),.cwr-sidebar .submenu-link:hover:not(:disabled){background-color:#0000000d}.cwr-sidebar.dark-theme{background-color:#2c3e50;color:#ecf0f1;border-right-color:#34495e}.cwr-sidebar.dark-theme .sidebar-header{background-color:#ffffff0d;border-bottom-color:#34495e}.cwr-sidebar.dark-theme .menu-link:hover{background-color:#ffffff1a}.cwr-sidebar.dark-theme .menu-link:focus{outline-color:#3498db}.cwr-sidebar.dark-theme .submenu-list{background-color:#0000004d}.cwr-sidebar.dark-theme .submenu-item:hover>.submenu-link{background-color:#ffffff1a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
181
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: Sidebar, isStandalone: true, selector: "cwr-sidebar", inputs: { menuItems: "menuItems", config: "config", collapsed: "collapsed", logoUrl: "logoUrl", logoAlt: "logoAlt", showToggle: "showToggle" }, outputs: { menuItemClicked: "menuItemClicked", collapsedChange: "collapsedChange", itemBadgeClick: "itemBadgeClick" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"sidebar d-flex flex-column justify-content-between\" [class.isOpen]=\"!isCollapsed\">\n <div>\n <!-- Logo Section -->\n <div class=\"d-flex justify-content-between logo pe-3 w-100\" *ngIf=\"logoUrl || showToggle\">\n <img *ngIf=\"logoUrl\" [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n <span\n class=\"icon-close_big d-md-none\"\n style=\"color: #fff; cursor: pointer\"\n [class.d-none]=\"isCollapsed\"\n (click)=\"closeSidebar()\"></span>\n </div>\n\n <!-- Navigation Wrapper -->\n <div class=\"nav-wrapper\" role=\"navigation\">\n <ul class=\"active\">\n <li \n *ngFor=\"let item of menuItems\"\n [class.active]=\"isActiveRoute(item)\"\n [class.disabled]=\"item.disabled\"\n >\n <a \n class=\"d-flex align-items-center w-100\"\n [routerLink]=\"item.route\"\n [routerLinkActive]=\"item.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(item)\"\n >\n <!-- Icon Section -->\n <div class=\"menu-icon-container\" *ngIf=\"item.icon\">\n <div [innerHTML]=\"item.icon\" class=\"svg-icon\"></div>\n </div>\n\n <!-- Label and Badge -->\n <div class=\"d-flex w-100 justify-content-between align-items-center\">\n <span class=\"nav-label\">{{ item.label }}</span>\n \n <!-- Badge -->\n <span \n class=\"badge-chip\"\n *ngIf=\"item.badge\"\n [style.background-color]=\"item.badge.color || '#28B48C'\"\n (click)=\"onBadgeClick($event, item)\"\n >\n {{ item.badge.text }}\n </span>\n </div>\n </a>\n\n <!-- Submenu -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasChildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n [class.active]=\"isActiveRoute(child)\"\n [class.disabled]=\"child.disabled\"\n >\n <a \n class=\"d-flex align-items-center submenu-link\"\n [routerLink]=\"child.route\"\n [routerLinkActive]=\"child.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(child)\"\n >\n <span class=\"nav-label\">{{ child.label }}</span>\n </a>\n </li>\n </ul>\n </li>\n </ul>\n </div>\n </div>\n\n <!-- Logout/Footer Section (optional) -->\n <div class=\"sidebar-footer\" *ngIf=\"!isCollapsed\">\n <slot name=\"footer\"></slot>\n </div>\n</div>\n", styles: [".sidebar{background:#141f2d;box-shadow:0 0 4px #0000001a;min-height:100vh;width:240px;border-right:1px solid #2C4057;font-family:Inter,sans-serif;position:fixed;top:0;left:0;z-index:300;transition:.5s;-webkit-transition:.5s;-moz-transition:.5s;display:flex;flex-direction:column;justify-content:space-between}.sidebar .d-flex{display:flex}.sidebar .flex-column{flex-direction:column}.sidebar .justify-content-between{justify-content:space-between}.sidebar .justify-content-center{justify-content:center}.sidebar .align-items-center{align-items:center}.sidebar .w-100{width:100%}.sidebar .pe-3{padding-right:1rem}.sidebar .d-md-none{display:none}.sidebar .d-none{display:none!important}.sidebar .me-12{margin-right:8px}.sidebar .badge-chip{display:flex;height:20px;padding:3px 6px;align-items:center;color:#fdfdfd;border-radius:4.5px;font-size:9px;font-weight:700;letter-spacing:.18px;text-align:center;white-space:nowrap;cursor:pointer;transition:all .3s ease}.sidebar .badge-chip:hover{opacity:.9;transform:scale(1.05)}.sidebar .fill-based-icons{fill:#3a4d63!important}.sidebar li.active .fill-based-icons{fill:#2c2b33!important}.sidebar li:not(.active) a:hover .fill-based-icons{fill:#fdfdfd!important}.sidebar .stroke-based-icons{stroke:#3a4d63!important}.sidebar li.active .stroke-based-icons{stroke:#2c2b33!important}.sidebar li:not(.active) a:hover .stroke-based-icons{stroke:#fdfdfd!important}.sidebar .nav-wrapper a{text-decoration:none;transition:all .3s ease}.sidebar .nav-wrapper .nav-label{font-weight:500;font-size:16px;line-height:19px;color:#3a4d63;transition:color .3s ease}.sidebar .nav-wrapper ul{list-style:none;padding:0;margin:0}.sidebar .nav-wrapper ul li{display:flex;justify-content:space-between;align-items:center;align-self:stretch;padding:8px 14px 8px 24px;height:52px;position:relative;transition:all .3s ease}.sidebar .nav-wrapper ul li.active{background:#28b48c;border-radius:0 8px 8px 0;margin-right:1.5rem}.sidebar .nav-wrapper ul li.active .nav-label,.sidebar .nav-wrapper ul li.active a:hover .nav-label{color:#2c2b33!important}.sidebar .nav-wrapper ul li:not(.active) a:hover .nav-label{color:#fdfdfd!important}.sidebar .nav-wrapper ul li.disabled{opacity:.5;cursor:not-allowed}.sidebar .nav-wrapper ul li.disabled a{pointer-events:none}.sidebar .nav-wrapper ul .submenu-list{list-style:none;padding:0;margin:0;background:#0003}.sidebar .nav-wrapper ul .submenu-list .submenu-item{padding:0;height:auto}.sidebar .nav-wrapper ul .submenu-list .submenu-item .submenu-link{padding:8px 14px 8px 48px;height:40px;display:flex;align-items:center;font-size:14px}.sidebar .nav-wrapper ul .submenu-list .submenu-item .submenu-link .nav-label{font-size:14px}.sidebar .logo{padding-top:36px;padding-left:24px;padding-bottom:66px}.sidebar .logo img{height:20px;object-fit:contain}.sidebar .menu-icon-container{display:flex;align-items:center;justify-content:center;min-width:24px}.sidebar .menu-icon-container .svg-icon{display:flex;align-items:center;justify-content:center}.sidebar .menu-icon-container .svg-icon svg{width:20px;height:20px}.sidebar .support{color:#3a4d63;padding:8px 26px;height:52px;font-weight:500;font-size:16px;cursor:pointer;text-align:center;text-decoration:none;transition:all .3s ease}.sidebar .support path,.sidebar .support circle{stroke:#3a4d63;transition:stroke .3s ease}.sidebar .support:hover{color:#fdfdfd!important}.sidebar .support:hover path,.sidebar .support:hover circle{stroke:#fdfdfd}.sidebar .logout{color:#ff677a;padding:8px 32px;font-weight:500;cursor:pointer;transition:all .3s ease}.sidebar .logout:hover{opacity:.8}.sidebar .icon-logout{color:#ff677a}.sidebar .sidebar-footer{padding:1rem;border-top:1px solid #2C4057}@media(max-width:768px){.sidebar{left:-240px;padding-bottom:50px;width:240px;transition:left .5s ease}.sidebar.isOpen{left:0!important;width:100%}.sidebar .d-md-none{display:block!important}.sidebar .icon-close_big{margin-right:1rem}}.d-flex{display:flex}.flex-column{flex-direction:column}.justify-content-between{justify-content:space-between}.align-items-center{align-items:center}.w-100{width:100%}.pe-3{padding-right:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
147
182
  }
148
183
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Sidebar, decorators: [{
149
184
  type: Component,
150
- args: [{ selector: 'cwr-sidebar', standalone: true, imports: [CommonModule, RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div \n class=\"cwr-sidebar\"\n [ngClass]=\"{ 'collapsed': (collapsed$ | async) }\"\n [style.width]=\"(collapsed$ | async) ? getConfig().collapsedWidth : getConfig().width\"\n [style.backgroundColor]=\"getConfig().backgroundColor\"\n [style.color]=\"getConfig().textColor\"\n>\n <!-- Toggle Button -->\n <div class=\"sidebar-header\" *ngIf=\"getConfig().toggleButton\">\n <button \n class=\"toggle-btn\" \n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"(collapsed$ | async) ? 'Expand sidebar' : 'Collapse sidebar'\"\n >\n <span class=\"toggle-icon\">\u2630</span>\n </button>\n <span class=\"header-title\" *ngIf=\"!(collapsed$ | async)\">Menu</span>\n </div>\n\n <!-- Menu Items -->\n <nav class=\"sidebar-nav\">\n <ul class=\"menu-list\">\n <li \n *ngFor=\"let item of menuItems\"\n class=\"menu-item\"\n [ngClass]=\"{ \n 'has-children': hasCildren(item),\n 'expanded': isExpanded(item),\n 'disabled': item.disabled\n }\"\n >\n <button \n class=\"menu-link\"\n [routerLink]=\"item.route\"\n (click)=\"onMenuItemClick(item)\"\n [disabled]=\"item.disabled\"\n >\n <span class=\"menu-icon\" *ngIf=\"item.icon\">{{ item.icon }}</span>\n <span class=\"menu-label\" *ngIf=\"!(collapsed$ | async)\">\n {{ item.label }}\n </span>\n <span \n class=\"menu-badge\"\n *ngIf=\"item.badge && !(collapsed$ | async)\"\n [ngStyle]=\"{ 'background-color': item.badge.color || '#ff6b6b' }\"\n >\n {{ item.badge.text }}\n </span>\n <span \n class=\"expand-icon\"\n *ngIf=\"hasCildren(item)\"\n (click)=\"toggleExpand(item)\"\n [ngClass]=\"{ 'expanded': isExpanded(item) }\"\n >\n \u25BE\n </span>\n </button>\n\n <!-- Nested Menu Items -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasCildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n class=\"submenu-item\"\n [ngClass]=\"{ 'disabled': child.disabled }\"\n >\n <button \n class=\"submenu-link\"\n [routerLink]=\"child.route\"\n (click)=\"onMenuItemClick(child)\"\n [disabled]=\"child.disabled\"\n >\n <span class=\"submenu-icon\" *ngIf=\"child.icon\">{{ child.icon }}</span>\n <span class=\"submenu-label\">{{ child.label }}</span>\n </button>\n </li>\n </ul>\n </li>\n </ul>\n </nav>\n</div>\n", styles: [".cwr-sidebar{display:flex;flex-direction:column;height:100vh;background-color:#f5f5f5;color:#333;border-right:1px solid #ddd;overflow:hidden;transition:width .3s ease-in-out;position:relative;z-index:1000}.cwr-sidebar.collapsed{width:60px}.cwr-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1rem;border-bottom:1px solid #ddd;background-color:#00000005}.cwr-sidebar .sidebar-header .toggle-btn{background:transparent;border:none;cursor:pointer;padding:.5rem;display:flex;align-items:center;justify-content:center;color:#333;font-size:1.2rem;transition:background-color .3s,color .3s;border-radius:4px}.cwr-sidebar .sidebar-header .toggle-btn:hover{background-color:#e0e0e0;color:#007bff}.cwr-sidebar .sidebar-header .toggle-btn:active{transform:scale(.95)}.cwr-sidebar .sidebar-header .toggle-btn .toggle-icon{display:block}.cwr-sidebar .sidebar-header .header-title{flex:1;margin-left:.5rem;font-weight:600;font-size:.95rem;text-transform:uppercase;letter-spacing:.5px}.cwr-sidebar .sidebar-nav{flex:1;overflow-y:auto;overflow-x:hidden;padding:.5rem 0}.cwr-sidebar .sidebar-nav::-webkit-scrollbar{width:6px}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-track{background:transparent}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-thumb{background:#ccc;border-radius:3px}.cwr-sidebar .sidebar-nav::-webkit-scrollbar-thumb:hover{background:#999}.cwr-sidebar .menu-list{list-style:none;padding:0;margin:0}.cwr-sidebar .menu-item{position:relative;transition:background-color .3s}.cwr-sidebar .menu-item.disabled{opacity:.5;cursor:not-allowed}.cwr-sidebar .menu-item:hover>.menu-link{background-color:#e0e0e0}.cwr-sidebar .menu-link{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 1rem;background:transparent;border:none;color:inherit;cursor:pointer;font-size:.95rem;text-align:left;transition:background-color .3s,color .3s;position:relative}.cwr-sidebar .menu-link:hover:not(:disabled){color:#007bff}.cwr-sidebar .menu-link:disabled{cursor:not-allowed}.cwr-sidebar .menu-link:focus{outline:2px solid #007bff;outline-offset:-2px}.cwr-sidebar .menu-link .menu-icon{display:flex;align-items:center;justify-content:center;min-width:24px;font-size:1.1rem;margin-right:.75rem}.cwr-sidebar .menu-link .menu-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cwr-sidebar .menu-link .menu-badge{display:inline-block;padding:.25rem .5rem;border-radius:12px;font-size:.75rem;font-weight:600;color:#fff;margin:0 .5rem;white-space:nowrap}.cwr-sidebar .menu-link .expand-icon{display:flex;align-items:center;justify-content:center;margin-left:.5rem;font-size:.75rem;transition:transform .3s;cursor:pointer}.cwr-sidebar .menu-link .expand-icon.expanded{transform:rotate(180deg)}.cwr-sidebar .submenu-list{list-style:none;padding:0;margin:0;background-color:#0000000d;max-height:none;overflow:visible;animation:slideDown .3s ease-in-out}.cwr-sidebar .submenu-item{position:relative;transition:background-color .3s}.cwr-sidebar .submenu-item.disabled{opacity:.5;cursor:not-allowed}.cwr-sidebar .submenu-item:hover>.submenu-link{background-color:#00000014}.cwr-sidebar .submenu-link{display:flex;align-items:center;width:100%;padding:.6rem 1rem .6rem 3rem;background:transparent;border:none;color:inherit;cursor:pointer;font-size:.9rem;text-align:left;transition:background-color .3s,color .3s}.cwr-sidebar .submenu-link:hover:not(:disabled){color:#007bff;background-color:#00000014}.cwr-sidebar .submenu-link:disabled{cursor:not-allowed}.cwr-sidebar .submenu-link:focus{outline:2px solid #007bff;outline-offset:-2px}.cwr-sidebar .submenu-link .submenu-icon{display:flex;align-items:center;justify-content:center;min-width:20px;font-size:1rem;margin-right:.75rem}.cwr-sidebar .submenu-link .submenu-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.cwr-sidebar{position:absolute;left:0;top:0;bottom:0;box-shadow:0 2px 10px #0003}.cwr-sidebar.collapsed{transform:translate(-100%);width:250px}.cwr-sidebar .sidebar-nav{height:calc(100vh - 60px)}}.cwr-sidebar{--sidebar-color: #f5f5f5;--text-color: #333}.cwr-sidebar .menu-link,.cwr-sidebar .submenu-link{color:var(--text-color)}.cwr-sidebar .menu-link:hover:not(:disabled),.cwr-sidebar .submenu-link:hover:not(:disabled){background-color:#0000000d}.cwr-sidebar.dark-theme{background-color:#2c3e50;color:#ecf0f1;border-right-color:#34495e}.cwr-sidebar.dark-theme .sidebar-header{background-color:#ffffff0d;border-bottom-color:#34495e}.cwr-sidebar.dark-theme .menu-link:hover{background-color:#ffffff1a}.cwr-sidebar.dark-theme .menu-link:focus{outline-color:#3498db}.cwr-sidebar.dark-theme .submenu-list{background-color:#0000004d}.cwr-sidebar.dark-theme .submenu-item:hover>.submenu-link{background-color:#ffffff1a}\n"] }]
185
+ args: [{ selector: 'cwr-sidebar', standalone: true, imports: [CommonModule, RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sidebar d-flex flex-column justify-content-between\" [class.isOpen]=\"!isCollapsed\">\n <div>\n <!-- Logo Section -->\n <div class=\"d-flex justify-content-between logo pe-3 w-100\" *ngIf=\"logoUrl || showToggle\">\n <img *ngIf=\"logoUrl\" [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n <span\n class=\"icon-close_big d-md-none\"\n style=\"color: #fff; cursor: pointer\"\n [class.d-none]=\"isCollapsed\"\n (click)=\"closeSidebar()\"></span>\n </div>\n\n <!-- Navigation Wrapper -->\n <div class=\"nav-wrapper\" role=\"navigation\">\n <ul class=\"active\">\n <li \n *ngFor=\"let item of menuItems\"\n [class.active]=\"isActiveRoute(item)\"\n [class.disabled]=\"item.disabled\"\n >\n <a \n class=\"d-flex align-items-center w-100\"\n [routerLink]=\"item.route\"\n [routerLinkActive]=\"item.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(item)\"\n >\n <!-- Icon Section -->\n <div class=\"menu-icon-container\" *ngIf=\"item.icon\">\n <div [innerHTML]=\"item.icon\" class=\"svg-icon\"></div>\n </div>\n\n <!-- Label and Badge -->\n <div class=\"d-flex w-100 justify-content-between align-items-center\">\n <span class=\"nav-label\">{{ item.label }}</span>\n \n <!-- Badge -->\n <span \n class=\"badge-chip\"\n *ngIf=\"item.badge\"\n [style.background-color]=\"item.badge.color || '#28B48C'\"\n (click)=\"onBadgeClick($event, item)\"\n >\n {{ item.badge.text }}\n </span>\n </div>\n </a>\n\n <!-- Submenu -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasChildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n [class.active]=\"isActiveRoute(child)\"\n [class.disabled]=\"child.disabled\"\n >\n <a \n class=\"d-flex align-items-center submenu-link\"\n [routerLink]=\"child.route\"\n [routerLinkActive]=\"child.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(child)\"\n >\n <span class=\"nav-label\">{{ child.label }}</span>\n </a>\n </li>\n </ul>\n </li>\n </ul>\n </div>\n </div>\n\n <!-- Logout/Footer Section (optional) -->\n <div class=\"sidebar-footer\" *ngIf=\"!isCollapsed\">\n <slot name=\"footer\"></slot>\n </div>\n</div>\n", styles: [".sidebar{background:#141f2d;box-shadow:0 0 4px #0000001a;min-height:100vh;width:240px;border-right:1px solid #2C4057;font-family:Inter,sans-serif;position:fixed;top:0;left:0;z-index:300;transition:.5s;-webkit-transition:.5s;-moz-transition:.5s;display:flex;flex-direction:column;justify-content:space-between}.sidebar .d-flex{display:flex}.sidebar .flex-column{flex-direction:column}.sidebar .justify-content-between{justify-content:space-between}.sidebar .justify-content-center{justify-content:center}.sidebar .align-items-center{align-items:center}.sidebar .w-100{width:100%}.sidebar .pe-3{padding-right:1rem}.sidebar .d-md-none{display:none}.sidebar .d-none{display:none!important}.sidebar .me-12{margin-right:8px}.sidebar .badge-chip{display:flex;height:20px;padding:3px 6px;align-items:center;color:#fdfdfd;border-radius:4.5px;font-size:9px;font-weight:700;letter-spacing:.18px;text-align:center;white-space:nowrap;cursor:pointer;transition:all .3s ease}.sidebar .badge-chip:hover{opacity:.9;transform:scale(1.05)}.sidebar .fill-based-icons{fill:#3a4d63!important}.sidebar li.active .fill-based-icons{fill:#2c2b33!important}.sidebar li:not(.active) a:hover .fill-based-icons{fill:#fdfdfd!important}.sidebar .stroke-based-icons{stroke:#3a4d63!important}.sidebar li.active .stroke-based-icons{stroke:#2c2b33!important}.sidebar li:not(.active) a:hover .stroke-based-icons{stroke:#fdfdfd!important}.sidebar .nav-wrapper a{text-decoration:none;transition:all .3s ease}.sidebar .nav-wrapper .nav-label{font-weight:500;font-size:16px;line-height:19px;color:#3a4d63;transition:color .3s ease}.sidebar .nav-wrapper ul{list-style:none;padding:0;margin:0}.sidebar .nav-wrapper ul li{display:flex;justify-content:space-between;align-items:center;align-self:stretch;padding:8px 14px 8px 24px;height:52px;position:relative;transition:all .3s ease}.sidebar .nav-wrapper ul li.active{background:#28b48c;border-radius:0 8px 8px 0;margin-right:1.5rem}.sidebar .nav-wrapper ul li.active .nav-label,.sidebar .nav-wrapper ul li.active a:hover .nav-label{color:#2c2b33!important}.sidebar .nav-wrapper ul li:not(.active) a:hover .nav-label{color:#fdfdfd!important}.sidebar .nav-wrapper ul li.disabled{opacity:.5;cursor:not-allowed}.sidebar .nav-wrapper ul li.disabled a{pointer-events:none}.sidebar .nav-wrapper ul .submenu-list{list-style:none;padding:0;margin:0;background:#0003}.sidebar .nav-wrapper ul .submenu-list .submenu-item{padding:0;height:auto}.sidebar .nav-wrapper ul .submenu-list .submenu-item .submenu-link{padding:8px 14px 8px 48px;height:40px;display:flex;align-items:center;font-size:14px}.sidebar .nav-wrapper ul .submenu-list .submenu-item .submenu-link .nav-label{font-size:14px}.sidebar .logo{padding-top:36px;padding-left:24px;padding-bottom:66px}.sidebar .logo img{height:20px;object-fit:contain}.sidebar .menu-icon-container{display:flex;align-items:center;justify-content:center;min-width:24px}.sidebar .menu-icon-container .svg-icon{display:flex;align-items:center;justify-content:center}.sidebar .menu-icon-container .svg-icon svg{width:20px;height:20px}.sidebar .support{color:#3a4d63;padding:8px 26px;height:52px;font-weight:500;font-size:16px;cursor:pointer;text-align:center;text-decoration:none;transition:all .3s ease}.sidebar .support path,.sidebar .support circle{stroke:#3a4d63;transition:stroke .3s ease}.sidebar .support:hover{color:#fdfdfd!important}.sidebar .support:hover path,.sidebar .support:hover circle{stroke:#fdfdfd}.sidebar .logout{color:#ff677a;padding:8px 32px;font-weight:500;cursor:pointer;transition:all .3s ease}.sidebar .logout:hover{opacity:.8}.sidebar .icon-logout{color:#ff677a}.sidebar .sidebar-footer{padding:1rem;border-top:1px solid #2C4057}@media(max-width:768px){.sidebar{left:-240px;padding-bottom:50px;width:240px;transition:left .5s ease}.sidebar.isOpen{left:0!important;width:100%}.sidebar .d-md-none{display:block!important}.sidebar .icon-close_big{margin-right:1rem}}.d-flex{display:flex}.flex-column{flex-direction:column}.justify-content-between{justify-content:space-between}.align-items-center{align-items:center}.w-100{width:100%}.pe-3{padding-right:1rem}\n"] }]
151
186
  }], propDecorators: { menuItems: [{
152
187
  type: Input
153
188
  }], config: [{
154
189
  type: Input
190
+ }], collapsed: [{
191
+ type: Input
192
+ }], logoUrl: [{
193
+ type: Input
194
+ }], logoAlt: [{
195
+ type: Input
196
+ }], showToggle: [{
197
+ type: Input
155
198
  }], menuItemClicked: [{
156
199
  type: Output
157
200
  }], collapsedChange: [{
158
201
  type: Output
202
+ }], itemBadgeClick: [{
203
+ type: Output
159
204
  }] } });
160
205
 
161
206
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"elavarasanbititude-ng-cwr-sidebar.mjs","sources":["../../../packages/ng-cwr-sidebar/src/lib/services/sidebar.service.ts","../../../packages/ng-cwr-sidebar/src/lib/sidebar/sidebar.ts","../../../packages/ng-cwr-sidebar/src/lib/sidebar/sidebar.html","../../../packages/ng-cwr-sidebar/src/public-api.ts","../../../packages/ng-cwr-sidebar/src/elavarasanbititude-ng-cwr-sidebar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { SidebarConfig, SidebarMenuItem } from '../models/sidebar.model';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SidebarService {\n private collapsedSubject = new BehaviorSubject<boolean>(false);\n private menuItemsSubject = new BehaviorSubject<SidebarMenuItem[]>([]);\n private configSubject = new BehaviorSubject<SidebarConfig>({});\n\n public collapsed$ = this.collapsedSubject.asObservable();\n public menuItems$ = this.menuItemsSubject.asObservable();\n public config$ = this.configSubject.asObservable();\n\n constructor() {}\n\n /**\n * Toggle the sidebar collapsed state\n */\n toggleCollapsed(): void {\n this.collapsedSubject.next(!this.collapsedSubject.value);\n }\n\n /**\n * Set the collapsed state\n */\n setCollapsed(collapsed: boolean): void {\n this.collapsedSubject.next(collapsed);\n }\n\n /**\n * Get current collapsed state\n */\n getCollapsed(): boolean {\n return this.collapsedSubject.value;\n }\n\n /**\n * Set menu items\n */\n setMenuItems(items: SidebarMenuItem[]): void {\n this.menuItemsSubject.next(items);\n }\n\n /**\n * Get menu items\n */\n getMenuItems(): SidebarMenuItem[] {\n return this.menuItemsSubject.value;\n }\n\n /**\n * Add a menu item\n */\n addMenuItem(item: SidebarMenuItem): void {\n const items = this.menuItemsSubject.value;\n this.menuItemsSubject.next([...items, item]);\n }\n\n /**\n * Remove a menu item by id\n */\n removeMenuItem(id: string): void {\n const items = this.menuItemsSubject.value.filter(item => item.id !== id);\n this.menuItemsSubject.next(items);\n }\n\n /**\n * Update sidebar configuration\n */\n setConfig(config: SidebarConfig): void {\n this.configSubject.next(config);\n }\n\n /**\n * Get sidebar configuration\n */\n getConfig(): SidebarConfig {\n return this.configSubject.value;\n }\n}\n","import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { SidebarService } from '../services/sidebar.service';\nimport { SidebarConfig, SidebarMenuItem } from '../models/sidebar.model';\n\n@Component({\n selector: 'cwr-sidebar',\n standalone: true,\n imports: [CommonModule, RouterModule],\n templateUrl: './sidebar.html',\n styleUrl: './sidebar.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class Sidebar implements OnInit {\n @Input() menuItems: SidebarMenuItem[] = [];\n @Input() config: SidebarConfig = {};\n @Output() menuItemClicked = new EventEmitter<SidebarMenuItem>();\n @Output() collapsedChange = new EventEmitter<boolean>();\n\n private sidebarService = inject(SidebarService);\n\n get collapsed$() {\n return this.sidebarService.collapsed$;\n }\n\n expandedItems: Set<string> = new Set();\n\n readonly defaultConfig: SidebarConfig = {\n collapsed: false,\n position: 'left',\n width: '250px',\n collapsedWidth: '60px',\n backgroundColor: '#f5f5f5',\n textColor: '#333',\n hoverColor: '#e0e0e0',\n toggleButton: true,\n overlayOnMobile: true,\n };\n\n ngOnInit(): void {\n this.sidebarService.setMenuItems(this.menuItems);\n const mergedConfig = { ...this.defaultConfig, ...this.config };\n this.sidebarService.setConfig(mergedConfig);\n }\n\n ngOnChanges(): void {\n if (this.menuItems.length > 0) {\n this.sidebarService.setMenuItems(this.menuItems);\n }\n }\n\n toggleSidebar(): void {\n this.sidebarService.toggleCollapsed();\n this.collapsedChange.emit(this.sidebarService.getCollapsed());\n }\n\n toggleExpand(item: SidebarMenuItem): void {\n if (item.children && item.children.length > 0) {\n const itemId = item.id || item.label;\n if (this.expandedItems.has(itemId)) {\n this.expandedItems.delete(itemId);\n } else {\n this.expandedItems.add(itemId);\n }\n }\n }\n\n isExpanded(item: SidebarMenuItem): boolean {\n const itemId = item.id || item.label;\n return this.expandedItems.has(itemId);\n }\n\n onMenuItemClick(item: SidebarMenuItem): void {\n if (item.action) {\n item.action();\n }\n this.menuItemClicked.emit(item);\n }\n\n hasCildren(item: SidebarMenuItem): boolean {\n return !!(item.children && item.children.length > 0);\n }\n\n getConfig(): SidebarConfig {\n return this.sidebarService.getConfig();\n }\n}\n","<div \n class=\"cwr-sidebar\"\n [ngClass]=\"{ 'collapsed': (collapsed$ | async) }\"\n [style.width]=\"(collapsed$ | async) ? getConfig().collapsedWidth : getConfig().width\"\n [style.backgroundColor]=\"getConfig().backgroundColor\"\n [style.color]=\"getConfig().textColor\"\n>\n <!-- Toggle Button -->\n <div class=\"sidebar-header\" *ngIf=\"getConfig().toggleButton\">\n <button \n class=\"toggle-btn\" \n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"(collapsed$ | async) ? 'Expand sidebar' : 'Collapse sidebar'\"\n >\n <span class=\"toggle-icon\">☰</span>\n </button>\n <span class=\"header-title\" *ngIf=\"!(collapsed$ | async)\">Menu</span>\n </div>\n\n <!-- Menu Items -->\n <nav class=\"sidebar-nav\">\n <ul class=\"menu-list\">\n <li \n *ngFor=\"let item of menuItems\"\n class=\"menu-item\"\n [ngClass]=\"{ \n 'has-children': hasCildren(item),\n 'expanded': isExpanded(item),\n 'disabled': item.disabled\n }\"\n >\n <button \n class=\"menu-link\"\n [routerLink]=\"item.route\"\n (click)=\"onMenuItemClick(item)\"\n [disabled]=\"item.disabled\"\n >\n <span class=\"menu-icon\" *ngIf=\"item.icon\">{{ item.icon }}</span>\n <span class=\"menu-label\" *ngIf=\"!(collapsed$ | async)\">\n {{ item.label }}\n </span>\n <span \n class=\"menu-badge\"\n *ngIf=\"item.badge && !(collapsed$ | async)\"\n [ngStyle]=\"{ 'background-color': item.badge.color || '#ff6b6b' }\"\n >\n {{ item.badge.text }}\n </span>\n <span \n class=\"expand-icon\"\n *ngIf=\"hasCildren(item)\"\n (click)=\"toggleExpand(item)\"\n [ngClass]=\"{ 'expanded': isExpanded(item) }\"\n >\n ▾\n </span>\n </button>\n\n <!-- Nested Menu Items -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasCildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n class=\"submenu-item\"\n [ngClass]=\"{ 'disabled': child.disabled }\"\n >\n <button \n class=\"submenu-link\"\n [routerLink]=\"child.route\"\n (click)=\"onMenuItemClick(child)\"\n [disabled]=\"child.disabled\"\n >\n <span class=\"submenu-icon\" *ngIf=\"child.icon\">{{ child.icon }}</span>\n <span class=\"submenu-label\">{{ child.label }}</span>\n </button>\n </li>\n </ul>\n </li>\n </ul>\n </nav>\n</div>\n","/*\n * Public API Surface of ng-cwr-sidebar\n */\n\nexport * from './lib/sidebar/sidebar';\nexport * from './lib/services/sidebar.service';\nexport * from './lib/models/sidebar.model';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"elavarasanbititude-ng-cwr-sidebar.mjs","sources":["../../../packages/ng-cwr-sidebar/src/lib/services/sidebar.service.ts","../../../packages/ng-cwr-sidebar/src/lib/sidebar/sidebar.ts","../../../packages/ng-cwr-sidebar/src/lib/sidebar/sidebar.html","../../../packages/ng-cwr-sidebar/src/public-api.ts","../../../packages/ng-cwr-sidebar/src/elavarasanbititude-ng-cwr-sidebar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { SidebarConfig, SidebarMenuItem } from '../models/sidebar.model';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SidebarService {\n private collapsedSubject = new BehaviorSubject<boolean>(false);\n private menuItemsSubject = new BehaviorSubject<SidebarMenuItem[]>([]);\n private configSubject = new BehaviorSubject<SidebarConfig>({});\n\n public collapsed$ = this.collapsedSubject.asObservable();\n public menuItems$ = this.menuItemsSubject.asObservable();\n public config$ = this.configSubject.asObservable();\n\n constructor() {}\n\n /**\n * Toggle the sidebar collapsed state\n */\n toggleCollapsed(): void {\n this.collapsedSubject.next(!this.collapsedSubject.value);\n }\n\n /**\n * Set the collapsed state\n */\n setCollapsed(collapsed: boolean): void {\n this.collapsedSubject.next(collapsed);\n }\n\n /**\n * Get current collapsed state\n */\n getCollapsed(): boolean {\n return this.collapsedSubject.value;\n }\n\n /**\n * Set menu items\n */\n setMenuItems(items: SidebarMenuItem[]): void {\n this.menuItemsSubject.next(items);\n }\n\n /**\n * Get menu items\n */\n getMenuItems(): SidebarMenuItem[] {\n return this.menuItemsSubject.value;\n }\n\n /**\n * Add a menu item\n */\n addMenuItem(item: SidebarMenuItem): void {\n const items = this.menuItemsSubject.value;\n this.menuItemsSubject.next([...items, item]);\n }\n\n /**\n * Remove a menu item by id\n */\n removeMenuItem(id: string): void {\n const items = this.menuItemsSubject.value.filter(item => item.id !== id);\n this.menuItemsSubject.next(items);\n }\n\n /**\n * Update sidebar configuration\n */\n setConfig(config: SidebarConfig): void {\n this.configSubject.next(config);\n }\n\n /**\n * Get sidebar configuration\n */\n getConfig(): SidebarConfig {\n return this.configSubject.value;\n }\n}\n","import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectionStrategy, inject, SimpleChanges } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterModule, Router, NavigationEnd } from '@angular/router';\nimport { SidebarService } from '../services/sidebar.service';\nimport { SidebarConfig, SidebarMenuItem } from '../models/sidebar.model';\nimport { filter } from 'rxjs/operators';\n\n@Component({\n selector: 'cwr-sidebar',\n standalone: true,\n imports: [CommonModule, RouterModule],\n templateUrl: './sidebar.html',\n styleUrl: './sidebar.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class Sidebar implements OnInit, OnChanges {\n @Input() menuItems: SidebarMenuItem[] = [];\n @Input() config: SidebarConfig = {};\n @Input() collapsed: boolean = false;\n @Input() logoUrl?: string;\n @Input() logoAlt: string = 'Logo';\n @Input() showToggle: boolean = true;\n @Output() menuItemClicked = new EventEmitter<SidebarMenuItem>();\n @Output() collapsedChange = new EventEmitter<boolean>();\n @Output() itemBadgeClick = new EventEmitter<SidebarMenuItem>();\n\n private sidebarService = inject(SidebarService);\n private router = inject(Router);\n\n get collapsed$() {\n return this.sidebarService.collapsed$;\n }\n\n expandedItems: Set<string> = new Set();\n isCollapsed = false;\n\n readonly defaultConfig: SidebarConfig = {\n collapsed: false,\n position: 'left',\n width: '240px',\n collapsedWidth: '60px',\n backgroundColor: '#141F2D',\n textColor: '#3A4D63',\n hoverColor: '#FDFDFD',\n toggleButton: true,\n overlayOnMobile: true,\n };\n\n ngOnInit(): void {\n this.isCollapsed = this.collapsed;\n this.sidebarService.setMenuItems(this.menuItems);\n const mergedConfig = { ...this.defaultConfig, ...this.config };\n this.sidebarService.setConfig(mergedConfig);\n\n // Track router navigation for active state\n this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {\n // Trigger change detection for route changes\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['menuItems'] && !changes['menuItems'].firstChange) {\n this.sidebarService.setMenuItems(this.menuItems);\n }\n if (changes['collapsed']) {\n this.isCollapsed = this.collapsed;\n }\n if (changes['config'] && !changes['config'].firstChange) {\n this.sidebarService.setConfig({ ...this.defaultConfig, ...this.config });\n }\n }\n\n toggleSidebar(): void {\n this.isCollapsed = !this.isCollapsed;\n this.sidebarService.toggleCollapsed();\n this.collapsedChange.emit(this.isCollapsed);\n }\n\n toggleExpand(item: SidebarMenuItem): void {\n if (item.children && item.children.length > 0) {\n const itemId = item.id || item.label;\n if (this.expandedItems.has(itemId)) {\n this.expandedItems.delete(itemId);\n } else {\n this.expandedItems.add(itemId);\n }\n }\n }\n\n isExpanded(item: SidebarMenuItem): boolean {\n const itemId = item.id || item.label;\n return this.expandedItems.has(itemId);\n }\n\n onMenuItemClick(item: SidebarMenuItem): void {\n if (item.action) {\n item.action();\n }\n this.menuItemClicked.emit(item);\n }\n\n onBadgeClick(event: Event, item: SidebarMenuItem): void {\n event.stopPropagation();\n this.itemBadgeClick.emit(item);\n }\n\n hasChildren(item: SidebarMenuItem): boolean {\n return !!(item.children && item.children.length > 0);\n }\n\n isActiveRoute(item: SidebarMenuItem): boolean {\n if (item.isActive) {\n return item.isActive();\n }\n return item.route ? this.router.url.includes(`/${item.route}`) : false;\n }\n\n getConfig(): SidebarConfig {\n return this.sidebarService.getConfig();\n }\n\n closeSidebar(): void {\n if (!this.isCollapsed) {\n this.toggleSidebar();\n }\n }\n}\n","<div class=\"sidebar d-flex flex-column justify-content-between\" [class.isOpen]=\"!isCollapsed\">\n <div>\n <!-- Logo Section -->\n <div class=\"d-flex justify-content-between logo pe-3 w-100\" *ngIf=\"logoUrl || showToggle\">\n <img *ngIf=\"logoUrl\" [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n <span\n class=\"icon-close_big d-md-none\"\n style=\"color: #fff; cursor: pointer\"\n [class.d-none]=\"isCollapsed\"\n (click)=\"closeSidebar()\"></span>\n </div>\n\n <!-- Navigation Wrapper -->\n <div class=\"nav-wrapper\" role=\"navigation\">\n <ul class=\"active\">\n <li \n *ngFor=\"let item of menuItems\"\n [class.active]=\"isActiveRoute(item)\"\n [class.disabled]=\"item.disabled\"\n >\n <a \n class=\"d-flex align-items-center w-100\"\n [routerLink]=\"item.route\"\n [routerLinkActive]=\"item.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(item)\"\n >\n <!-- Icon Section -->\n <div class=\"menu-icon-container\" *ngIf=\"item.icon\">\n <div [innerHTML]=\"item.icon\" class=\"svg-icon\"></div>\n </div>\n\n <!-- Label and Badge -->\n <div class=\"d-flex w-100 justify-content-between align-items-center\">\n <span class=\"nav-label\">{{ item.label }}</span>\n \n <!-- Badge -->\n <span \n class=\"badge-chip\"\n *ngIf=\"item.badge\"\n [style.background-color]=\"item.badge.color || '#28B48C'\"\n (click)=\"onBadgeClick($event, item)\"\n >\n {{ item.badge.text }}\n </span>\n </div>\n </a>\n\n <!-- Submenu -->\n <ul \n class=\"submenu-list\"\n *ngIf=\"hasChildren(item) && isExpanded(item)\"\n >\n <li \n *ngFor=\"let child of item.children\"\n [class.active]=\"isActiveRoute(child)\"\n [class.disabled]=\"child.disabled\"\n >\n <a \n class=\"d-flex align-items-center submenu-link\"\n [routerLink]=\"child.route\"\n [routerLinkActive]=\"child.isActive ? '' : 'active'\"\n [routerLinkActiveOptions]=\"{ exact: false }\"\n (click)=\"onMenuItemClick(child)\"\n >\n <span class=\"nav-label\">{{ child.label }}</span>\n </a>\n </li>\n </ul>\n </li>\n </ul>\n </div>\n </div>\n\n <!-- Logout/Footer Section (optional) -->\n <div class=\"sidebar-footer\" *ngIf=\"!isCollapsed\">\n <slot name=\"footer\"></slot>\n </div>\n</div>\n","/*\n * Public API Surface of ng-cwr-sidebar\n */\n\nexport * from './lib/sidebar/sidebar';\nexport * from './lib/services/sidebar.service';\nexport * from './lib/models/sidebar.model';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elavarasanbititude/ng-cwr-sidebar",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A modern, flexible, and customizable Angular sidebar component library",
5
5
  "author": "elavarasanbititude",
6
6
  "license": "MIT",
@@ -1,7 +1,7 @@
1
1
  import * as rxjs from 'rxjs';
2
2
  import { Observable } from 'rxjs';
3
3
  import * as i0 from '@angular/core';
4
- import { OnInit, EventEmitter } from '@angular/core';
4
+ import { OnInit, OnChanges, EventEmitter, SimpleChanges } from '@angular/core';
5
5
 
6
6
  /**
7
7
  * Represents a menu item in the sidebar
@@ -18,6 +18,11 @@ interface SidebarMenuItem {
18
18
  text: string;
19
19
  color?: string;
20
20
  };
21
+ /**
22
+ * Custom function to determine if this item is active
23
+ * If provided, takes precedence over route-based active detection
24
+ */
25
+ isActive?: () => boolean;
21
26
  }
22
27
  /**
23
28
  * Configuration for the sidebar component
@@ -30,29 +35,40 @@ interface SidebarConfig {
30
35
  backgroundColor?: string;
31
36
  textColor?: string;
32
37
  hoverColor?: string;
38
+ activeColor?: string;
33
39
  toggleButton?: boolean;
34
40
  overlayOnMobile?: boolean;
35
41
  }
36
42
 
37
- declare class Sidebar implements OnInit {
43
+ declare class Sidebar implements OnInit, OnChanges {
38
44
  menuItems: SidebarMenuItem[];
39
45
  config: SidebarConfig;
46
+ collapsed: boolean;
47
+ logoUrl?: string;
48
+ logoAlt: string;
49
+ showToggle: boolean;
40
50
  menuItemClicked: EventEmitter<SidebarMenuItem>;
41
51
  collapsedChange: EventEmitter<boolean>;
52
+ itemBadgeClick: EventEmitter<SidebarMenuItem>;
42
53
  private sidebarService;
54
+ private router;
43
55
  get collapsed$(): rxjs.Observable<boolean>;
44
56
  expandedItems: Set<string>;
57
+ isCollapsed: boolean;
45
58
  readonly defaultConfig: SidebarConfig;
46
59
  ngOnInit(): void;
47
- ngOnChanges(): void;
60
+ ngOnChanges(changes: SimpleChanges): void;
48
61
  toggleSidebar(): void;
49
62
  toggleExpand(item: SidebarMenuItem): void;
50
63
  isExpanded(item: SidebarMenuItem): boolean;
51
64
  onMenuItemClick(item: SidebarMenuItem): void;
52
- hasCildren(item: SidebarMenuItem): boolean;
65
+ onBadgeClick(event: Event, item: SidebarMenuItem): void;
66
+ hasChildren(item: SidebarMenuItem): boolean;
67
+ isActiveRoute(item: SidebarMenuItem): boolean;
53
68
  getConfig(): SidebarConfig;
69
+ closeSidebar(): void;
54
70
  static ɵfac: i0.ɵɵFactoryDeclaration<Sidebar, never>;
55
- static ɵcmp: i0.ɵɵComponentDeclaration<Sidebar, "cwr-sidebar", never, { "menuItems": { "alias": "menuItems"; "required": false; }; "config": { "alias": "config"; "required": false; }; }, { "menuItemClicked": "menuItemClicked"; "collapsedChange": "collapsedChange"; }, never, never, true, never>;
71
+ static ɵcmp: i0.ɵɵComponentDeclaration<Sidebar, "cwr-sidebar", never, { "menuItems": { "alias": "menuItems"; "required": false; }; "config": { "alias": "config"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "logoUrl": { "alias": "logoUrl"; "required": false; }; "logoAlt": { "alias": "logoAlt"; "required": false; }; "showToggle": { "alias": "showToggle"; "required": false; }; }, { "menuItemClicked": "menuItemClicked"; "collapsedChange": "collapsedChange"; "itemBadgeClick": "itemBadgeClick"; }, never, never, true, never>;
56
72
  }
57
73
 
58
74
  declare class SidebarService {