commons-shared-web-ui 0.0.50 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/fesm2022/commons-shared-web-ui.mjs +14557 -0
  2. package/fesm2022/commons-shared-web-ui.mjs.map +1 -0
  3. package/index.d.ts +4534 -0
  4. package/package.json +34 -53
  5. package/src/lib/styles/utilities.scss +1 -0
  6. package/.claude/settings.local.json +0 -10
  7. package/documentation/alert.md +0 -123
  8. package/documentation/button-dropdown.md +0 -126
  9. package/documentation/button.md +0 -184
  10. package/documentation/cards-usage-guidelines.md +0 -131
  11. package/documentation/configurable-form.md +0 -605
  12. package/documentation/confirmation-modal.md +0 -250
  13. package/documentation/filter-sidebar.md +0 -178
  14. package/documentation/filter-table-selector.md +0 -228
  15. package/documentation/form-builder.md +0 -597
  16. package/documentation/form-components.md +0 -384
  17. package/documentation/nav.md +0 -427
  18. package/documentation/pagination.md +0 -181
  19. package/documentation/side-nav-documentation.md +0 -169
  20. package/documentation/smart-form.md +0 -2405
  21. package/documentation/smart-table.md +0 -1221
  22. package/documentation/snackbar.md +0 -118
  23. package/documentation/style-externalization.md +0 -88
  24. package/documentation/summary-card.md +0 -279
  25. package/ng-package.json +0 -28
  26. package/src/lib/modules/alert/alert.models.ts +0 -6
  27. package/src/lib/modules/alert/alert.module.ts +0 -16
  28. package/src/lib/modules/alert/components/alert/alert.component.html +0 -27
  29. package/src/lib/modules/alert/components/alert/alert.component.scss +0 -92
  30. package/src/lib/modules/alert/components/alert/alert.component.ts +0 -81
  31. package/src/lib/modules/button/button.models.ts +0 -13
  32. package/src/lib/modules/button/button.module.ts +0 -16
  33. package/src/lib/modules/button/components/button/button.component.html +0 -22
  34. package/src/lib/modules/button/components/button/button.component.scss +0 -88
  35. package/src/lib/modules/button/components/button/button.component.ts +0 -67
  36. package/src/lib/modules/button-dropdown/button-dropdown.models.ts +0 -26
  37. package/src/lib/modules/button-dropdown/button-dropdown.module.ts +0 -22
  38. package/src/lib/modules/button-dropdown/button-dropdown.theme.scss +0 -87
  39. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.html +0 -41
  40. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.scss +0 -135
  41. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.ts +0 -160
  42. package/src/lib/modules/configurable-form/component/configurable-form.component.html +0 -294
  43. package/src/lib/modules/configurable-form/component/configurable-form.component.scss +0 -503
  44. package/src/lib/modules/configurable-form/component/configurable-form.component.ts +0 -628
  45. package/src/lib/modules/configurable-form/configurable-form.examples.ts +0 -154
  46. package/src/lib/modules/configurable-form/configurable-form.model.ts +0 -131
  47. package/src/lib/modules/configurable-form/configurable-form.module.ts +0 -19
  48. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.html +0 -77
  49. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.scss +0 -395
  50. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.ts +0 -266
  51. package/src/lib/modules/confirmation-modal/confirmation-modal.models.ts +0 -71
  52. package/src/lib/modules/confirmation-modal/confirmation-modal.module.ts +0 -20
  53. package/src/lib/modules/filter/components/filter/filter.component.html +0 -131
  54. package/src/lib/modules/filter/components/filter/filter.component.scss +0 -245
  55. package/src/lib/modules/filter/components/filter/filter.component.ts +0 -216
  56. package/src/lib/modules/filter/filter.models.ts +0 -88
  57. package/src/lib/modules/filter/filter.module.ts +0 -24
  58. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.html +0 -112
  59. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.scss +0 -186
  60. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.ts +0 -163
  61. package/src/lib/modules/filter-sidebar/filter-sidebar.models.ts +0 -95
  62. package/src/lib/modules/filter-sidebar/filter-sidebar.module.ts +0 -24
  63. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.html +0 -73
  64. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.scss +0 -321
  65. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.ts +0 -361
  66. package/src/lib/modules/filter-table-selector/filter-table-selector.models.ts +0 -91
  67. package/src/lib/modules/filter-table-selector/filter-table-selector.module.ts +0 -22
  68. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.html +0 -63
  69. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.scss +0 -496
  70. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.ts +0 -445
  71. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.html +0 -75
  72. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.scss +0 -210
  73. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.ts +0 -55
  74. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.html +0 -25
  75. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.scss +0 -82
  76. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.ts +0 -95
  77. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.html +0 -20
  78. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.scss +0 -37
  79. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.ts +0 -94
  80. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.html +0 -46
  81. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.scss +0 -102
  82. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.ts +0 -50
  83. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.html +0 -35
  84. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.scss +0 -67
  85. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.ts +0 -34
  86. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.html +0 -68
  87. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.scss +0 -113
  88. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.ts +0 -74
  89. package/src/lib/modules/form-builder/configs/field-type-schema.map.ts +0 -533
  90. package/src/lib/modules/form-builder/form-builder.module.ts +0 -36
  91. package/src/lib/modules/form-builder/index.ts +0 -9
  92. package/src/lib/modules/form-builder/models/builder.models.ts +0 -7
  93. package/src/lib/modules/form-builder/models/field-configurator.models.ts +0 -38
  94. package/src/lib/modules/form-builder/models/field-selection.models.ts +0 -51
  95. package/src/lib/modules/form-builder/services/field-configurator.service.ts +0 -258
  96. package/src/lib/modules/form-builder/services/field-selection.service.ts +0 -299
  97. package/src/lib/modules/form-builder/services/form-schema-tree.service.ts +0 -670
  98. package/src/lib/modules/form-builder/tokens/builder.tokens.ts +0 -10
  99. package/src/lib/modules/form-builder/utils/constants.ts +0 -43
  100. package/src/lib/modules/form-components/components/checkbox/checkbox.component.html +0 -29
  101. package/src/lib/modules/form-components/components/checkbox/checkbox.component.scss +0 -111
  102. package/src/lib/modules/form-components/components/checkbox/checkbox.component.ts +0 -207
  103. package/src/lib/modules/form-components/components/checkbox/checkbox.models.ts +0 -35
  104. package/src/lib/modules/form-components/components/datepicker/datepicker.component.html +0 -42
  105. package/src/lib/modules/form-components/components/datepicker/datepicker.component.scss +0 -115
  106. package/src/lib/modules/form-components/components/datepicker/datepicker.component.ts +0 -267
  107. package/src/lib/modules/form-components/components/datepicker/datepicker.models.ts +0 -45
  108. package/src/lib/modules/form-components/components/dropdown/dropdown.component.html +0 -74
  109. package/src/lib/modules/form-components/components/dropdown/dropdown.component.scss +0 -252
  110. package/src/lib/modules/form-components/components/dropdown/dropdown.component.ts +0 -377
  111. package/src/lib/modules/form-components/components/dropdown/dropdown.models.ts +0 -53
  112. package/src/lib/modules/form-components/components/input/input.component.html +0 -51
  113. package/src/lib/modules/form-components/components/input/input.component.scss +0 -128
  114. package/src/lib/modules/form-components/components/input/input.component.ts +0 -250
  115. package/src/lib/modules/form-components/components/input/input.models.ts +0 -55
  116. package/src/lib/modules/form-components/components/radio/radio.component.html +0 -22
  117. package/src/lib/modules/form-components/components/radio/radio.component.scss +0 -107
  118. package/src/lib/modules/form-components/components/radio/radio.component.ts +0 -181
  119. package/src/lib/modules/form-components/components/radio/radio.models.ts +0 -39
  120. package/src/lib/modules/form-components/components/search/search.component.html +0 -15
  121. package/src/lib/modules/form-components/components/search/search.component.scss +0 -87
  122. package/src/lib/modules/form-components/components/search/search.component.ts +0 -213
  123. package/src/lib/modules/form-components/components/search/search.models.ts +0 -40
  124. package/src/lib/modules/form-components/components/toggle/toggle.component.html +0 -15
  125. package/src/lib/modules/form-components/components/toggle/toggle.component.scss +0 -81
  126. package/src/lib/modules/form-components/components/toggle/toggle.component.ts +0 -166
  127. package/src/lib/modules/form-components/components/toggle/toggle.models.ts +0 -27
  128. package/src/lib/modules/form-components/directives/click-outside.directive.ts +0 -22
  129. package/src/lib/modules/form-components/form-components.module.ts +0 -41
  130. package/src/lib/modules/material/material.module.ts +0 -94
  131. package/src/lib/modules/nav/components/nav/nav.component.html +0 -34
  132. package/src/lib/modules/nav/components/nav/nav.component.scss +0 -171
  133. package/src/lib/modules/nav/components/nav/nav.component.ts +0 -82
  134. package/src/lib/modules/nav/nav.models.ts +0 -31
  135. package/src/lib/modules/nav/nav.module.ts +0 -17
  136. package/src/lib/modules/pagination/components/pagination/pagination.component.html +0 -52
  137. package/src/lib/modules/pagination/components/pagination/pagination.component.scss +0 -155
  138. package/src/lib/modules/pagination/components/pagination/pagination.component.ts +0 -109
  139. package/src/lib/modules/pagination/pagination.module.ts +0 -17
  140. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.html +0 -56
  141. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.scss +0 -342
  142. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.ts +0 -135
  143. package/src/lib/modules/side-nav/side-nav.models.ts +0 -38
  144. package/src/lib/modules/side-nav/side-nav.module.ts +0 -16
  145. package/src/lib/modules/smart-form/components/form-field/form-field.component.html +0 -1196
  146. package/src/lib/modules/smart-form/components/form-field/form-field.component.scss +0 -2014
  147. package/src/lib/modules/smart-form/components/form-field/form-field.component.ts +0 -2525
  148. package/src/lib/modules/smart-form/components/form-section/form-section.component.html +0 -65
  149. package/src/lib/modules/smart-form/components/form-section/form-section.component.scss +0 -209
  150. package/src/lib/modules/smart-form/components/form-section/form-section.component.ts +0 -131
  151. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.html +0 -253
  152. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.scss +0 -689
  153. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.ts +0 -1124
  154. package/src/lib/modules/smart-form/index.ts +0 -10
  155. package/src/lib/modules/smart-form/models/form-schema.model.ts +0 -733
  156. package/src/lib/modules/smart-form/models/hierarchy-config.model.ts +0 -21
  157. package/src/lib/modules/smart-form/services/expression.service.ts +0 -75
  158. package/src/lib/modules/smart-form/services/smart-form-controller.service.ts +0 -65
  159. package/src/lib/modules/smart-form/smart-form.examples.ts +0 -1324
  160. package/src/lib/modules/smart-form/smart-form.module.ts +0 -36
  161. package/src/lib/modules/smart-form/utils/translation.utils.ts +0 -82
  162. package/src/lib/modules/smart-form/utils/trusted-url.pipe.ts +0 -25
  163. package/src/lib/modules/smart-form/utils/validation.utils.ts +0 -98
  164. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.html +0 -283
  165. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.scss +0 -685
  166. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.ts +0 -1128
  167. package/src/lib/modules/smart-table/models/table-config.model.ts +0 -207
  168. package/src/lib/modules/smart-table/smart-table.module.ts +0 -30
  169. package/src/lib/modules/smart-table/utils/safe-html.pipe.ts +0 -28
  170. package/src/lib/modules/smart-table/utils/smart-table.utils.ts +0 -18
  171. package/src/lib/modules/snackbar/components/snackbar.component.html +0 -41
  172. package/src/lib/modules/snackbar/components/snackbar.component.scss +0 -99
  173. package/src/lib/modules/snackbar/components/snackbar.component.ts +0 -18
  174. package/src/lib/modules/snackbar/models/snackbar.models.ts +0 -10
  175. package/src/lib/modules/snackbar/services/snackbar.service.ts +0 -40
  176. package/src/lib/modules/snackbar/snackbar.module.ts +0 -11
  177. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.html +0 -47
  178. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.scss +0 -199
  179. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.ts +0 -126
  180. package/src/lib/modules/summary-card/summary-card.module.ts +0 -18
  181. package/src/lib/shared-ui.module.ts +0 -44
  182. package/src/lib/utils/constants.ts +0 -11
  183. package/src/lib/utils/storage.utils.ts +0 -37
  184. package/src/lib/utils/string.utils.ts +0 -23
  185. package/src/lib/utils/translation.utils.ts +0 -87
  186. package/src/public-api.ts +0 -104
  187. package/tsconfig.lib.json +0 -15
@@ -1,109 +0,0 @@
1
- import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
2
- import { DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, PAGINATION_THEME_DEFAULT } from '../../../../utils/constants';
3
-
4
- export interface PaginationLabels {
5
- items: string;
6
- of: string;
7
- perPage: string;
8
- }
9
-
10
- @Component({
11
- selector: 'lib-pagination',
12
- templateUrl: './pagination.component.html',
13
- styleUrls: ['./pagination.component.scss'],
14
- standalone: false
15
- })
16
- export class PaginationComponent implements OnInit, OnChanges {
17
- @Input() totalItems: number = 0;
18
- @Input() itemsPerPage: number = DEFAULT_ITEMS_PER_PAGE;
19
- @Input() currentPage: number = 1;
20
- @Input() pageSizeOptions: number[] = DEFAULT_PAGE_SIZE_OPTIONS;
21
- @Input() theme: 'theme-1' | 'theme-2' = PAGINATION_THEME_DEFAULT;
22
- @Input() labels: PaginationLabels = {
23
- items: 'items',
24
- of: 'of',
25
- perPage: 'Per Page'
26
- };
27
-
28
- @Output() pageChange = new EventEmitter<number>();
29
- @Output() itemsPerPageChange = new EventEmitter<number>();
30
-
31
- totalPages: number = 0;
32
- pages: (number | string)[] = [];
33
- startItem: number = 0;
34
- endItem: number = 0;
35
-
36
- constructor() { }
37
-
38
- ngOnInit(): void {
39
- this.calculatePagination();
40
- }
41
-
42
- ngOnChanges(changes: SimpleChanges): void {
43
- if (changes['totalItems'] || changes['itemsPerPage'] || changes['currentPage']) {
44
- this.calculatePagination();
45
- }
46
- }
47
-
48
- calculatePagination(): void {
49
- this.totalPages = Math.ceil(this.totalItems / this.itemsPerPage);
50
-
51
- // Ensure current page is valid
52
- if (this.currentPage < 1) {
53
- this.currentPage = 1;
54
- } else if (this.currentPage > this.totalPages && this.totalPages > 0) {
55
- this.currentPage = this.totalPages;
56
- }
57
-
58
- this.startItem = (this.currentPage - 1) * this.itemsPerPage + 1;
59
- this.endItem = Math.min(this.currentPage * this.itemsPerPage, this.totalItems);
60
-
61
- if (this.totalItems === 0) {
62
- this.startItem = 0;
63
- this.endItem = 0;
64
- }
65
-
66
- this.pages = this.getVisiblePages(this.currentPage, this.totalPages);
67
- }
68
-
69
- getVisiblePages(current: number, total: number): (number | string)[] {
70
- if (total <= 7) {
71
- return Array.from({ length: total }, (_, i) => i + 1);
72
- }
73
-
74
- if (current <= 4) {
75
- return [1, 2, 3, 4, 5, '...', total];
76
- }
77
-
78
- if (current >= total - 3) {
79
- return [1, '...', total - 4, total - 3, total - 2, total - 1, total];
80
- }
81
-
82
- return [1, '...', current - 1, current, current + 1, '...', total];
83
- }
84
-
85
- onPageChange(page: number | string): void {
86
- if (typeof page === 'string') return;
87
- if (page < 1 || page > this.totalPages || page === this.currentPage) return;
88
-
89
- this.pageChange.emit(page);
90
- }
91
-
92
- onItemsPerPageChange(event: Event): void {
93
- const target = event.target as HTMLSelectElement;
94
- const newSize = Number(target.value);
95
- this.itemsPerPageChange.emit(newSize);
96
- }
97
-
98
- nextPage(): void {
99
- if (this.currentPage < this.totalPages) {
100
- this.onPageChange(this.currentPage + 1);
101
- }
102
- }
103
-
104
- prevPage(): void {
105
- if (this.currentPage > 1) {
106
- this.onPageChange(this.currentPage - 1);
107
- }
108
- }
109
- }
@@ -1,17 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { PaginationComponent } from './components/pagination/pagination.component';
4
-
5
-
6
- @NgModule({
7
- declarations: [
8
- PaginationComponent
9
- ],
10
- imports: [
11
- CommonModule
12
- ],
13
- exports: [
14
- PaginationComponent
15
- ]
16
- })
17
- export class PaginationModule { }
@@ -1,56 +0,0 @@
1
- <nav class="cc-side-nav" [class.collapsed]="collapsed" role="navigation" [ngStyle]="customStyles">
2
-
3
- <div class="cc-side-nav-section" *ngFor="let section of filteredSections; let i = index">
4
-
5
- <div class="cc-side-nav-heading-row" *ngIf="section.heading && !collapsed">
6
- <h3 class="cc-side-nav-heading">{{ section.heading }}</h3>
7
- </div>
8
-
9
- <ul class="cc-side-nav-list">
10
- <li *ngFor="let item of section.items" class="cc-side-nav-list-item">
11
- <a (click)="onItemClick(item, $event)" class="cc-side-nav-link" [class.active]="item.id === activeId"
12
- [class.disabled]="item.disabled" [matTooltip]="item.tooltip || item.label"
13
- [matTooltipDisabled]="collapsed ? false : !showTooltips" [matTooltipPosition]="tooltipPosition"
14
- [matTooltipClass]="'cc-side-nav-tooltip'" [attr.aria-current]="(item.id === activeId) ? 'page' : null"
15
- [attr.aria-disabled]="item.disabled ? true : null">
16
- <span *ngIf="item.icon && (collapsed || !hideIconsWhenExpanded)" class="cc-side-nav-icon">
17
- <span *ngIf="!item.icon.includes('fa') && !item.icon.includes('bi')" class="material-icons">
18
- {{ item.icon }}
19
- </span>
20
- <i *ngIf="item.icon.includes('fa') || item.icon.includes('bi')" [class]="item.icon"></i>
21
- </span>
22
- <!-- Label: always in DOM, CSS transitions handle fade on collapse -->
23
- <span class="cc-side-nav-label">{{ item.label }}</span>
24
- <!-- Arrow: rendered for active items regardless of collapse state; CSS hides it -->
25
- <span class="cc-side-nav-arrow material-icons"
26
- *ngIf="(item.id === activeId) && item.showArrow !== false">chevron_right</span>
27
- </a>
28
- </li>
29
- </ul>
30
-
31
- </div>
32
-
33
- </nav>
34
-
35
- <!--
36
- Toggle pill — always straddles the right edge of :host (right: -12px).
37
- Hidden via opacity/scale until :host is hovered; always visible when collapsed.
38
- Single chevron SVG rotates 180° via CSS — no icon swap needed.
39
- -->
40
- <button *ngIf="showCollapseToggle"
41
- class="cc-sn-toggle"
42
- (click)="toggleCollapse()"
43
- type="button"
44
- [attr.aria-label]="collapsed ? 'Expand navigation' : 'Collapse navigation'">
45
- <svg class="cc-sn-chevron"
46
- xmlns="http://www.w3.org/2000/svg"
47
- viewBox="0 0 16 16"
48
- fill="none"
49
- aria-hidden="true">
50
- <path d="M10 3L5 8L10 13"
51
- stroke="currentColor"
52
- stroke-width="1.75"
53
- stroke-linecap="round"
54
- stroke-linejoin="round"/>
55
- </svg>
56
- </button>
@@ -1,342 +0,0 @@
1
- @use "../../side-nav.theme" as side-nav;
2
-
3
- // ─── Host ──────────────────────────────────────────────────────────────────────
4
-
5
- :host {
6
- display: block;
7
- height: 100%;
8
- overflow: visible; // Critical: allows toggle pill to float outside :host bounds
9
- position: relative;
10
- width: var(--cc-side-nav-width, 220px);
11
- transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
12
-
13
- &.cc-side-nav-host-collapsed {
14
- width: var(--cc-side-nav-collapsed-width, 56px);
15
- }
16
-
17
- @include side-nav.side-nav-theme();
18
- }
19
-
20
- // ─── Edge Rail (hover affordance) ─────────────────────────────────────────────
21
- // A thin accent line on the right edge that appears on hover, hinting at the
22
- // interactive collapse zone (Linear/Notion-style spatial affordance).
23
-
24
- :host::after {
25
- content: '';
26
- position: absolute;
27
- top: 10%;
28
- right: 0;
29
- width: 2px;
30
- height: 80%;
31
- background: var(--cc-side-nav-active-bg, #1e1e2d);
32
- border-radius: 2px;
33
- opacity: 0;
34
- transition: opacity 0.25s ease;
35
- pointer-events: none;
36
- z-index: 4;
37
- }
38
-
39
- :host:hover::after {
40
- opacity: 0.18;
41
- }
42
-
43
- :host.cc-side-nav-host-collapsed::after {
44
- display: none;
45
- }
46
-
47
- // ─── Toggle Pill ──────────────────────────────────────────────────────────────
48
- // Circular button straddling the right edge (right: -12px keeps it half inside,
49
- // half outside). Hidden by default; spring-bounces in on :host hover.
50
- // When collapsed, always visible so the user can find it to re-expand.
51
-
52
- .cc-sn-toggle {
53
- position: absolute;
54
- top: 20px;
55
- right: -12px;
56
- width: 24px;
57
- height: 24px;
58
- border-radius: 50%;
59
- border: 1.5px solid var(--cc-side-nav-toggle-border-color, rgba(0, 0, 0, 0.1));
60
- background: var(--cc-side-nav-toggle-bg, #ffffff);
61
- cursor: pointer;
62
- display: flex;
63
- align-items: center;
64
- justify-content: center;
65
- z-index: 20;
66
- padding: 0;
67
- color: var(--cc-side-nav-item-color, #5F6368);
68
- box-shadow:
69
- 0 1px 4px rgba(0, 0, 0, 0.1),
70
- 0 0 0 1px rgba(0, 0, 0, 0.04);
71
-
72
- // Hidden by default; spring easing gives a satisfying pop on reveal
73
- opacity: 1;
74
- transform: scale(0.65);
75
- transition:
76
- opacity 0.2s ease,
77
- transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
78
- background 0.15s ease,
79
- color 0.15s ease,
80
- border-color 0.15s ease,
81
- box-shadow 0.2s ease;
82
-
83
- &:focus-visible {
84
- outline: 2px solid var(--cc-side-nav-active-bg, #E63E30);
85
- outline-offset: 2px;
86
- }
87
-
88
- // Chevron: single path, rotates 180° via :host class — no SVG swap
89
- .cc-sn-chevron {
90
- width: 12px;
91
- height: 12px;
92
- flex-shrink: 0;
93
- display: block;
94
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
95
- }
96
- }
97
-
98
- // Reveal pill when hovering anywhere on :host
99
- :host:hover .cc-sn-toggle {
100
- opacity: 1;
101
- transform: scale(1);
102
- }
103
-
104
- // Brand-colored hover state — only applies when the pill is actually visible
105
- :host:hover .cc-sn-toggle:hover,
106
- :host.cc-side-nav-host-collapsed .cc-sn-toggle:hover {
107
- background: var(--cc-side-nav-active-bg, #E63E30);
108
- color: var(--cc-side-nav-active-color, #ffffff);
109
- border-color: transparent;
110
- box-shadow:
111
- 0 4px 14px rgba(0, 0, 0, 0.1),
112
- 0 1px 4px rgba(0, 0, 0, 0.1);
113
- transform: scale(1.12);
114
- }
115
-
116
- // Collapsed: always show so user can expand; slightly elevated shadow
117
- :host.cc-side-nav-host-collapsed .cc-sn-toggle {
118
- opacity: 1;
119
- transform: scale(1);
120
- box-shadow:
121
- 0 2px 8px rgba(0, 0, 0, 0.13),
122
- 0 0 0 1.5px rgba(0, 0, 0, 0.08);
123
- }
124
-
125
- // Chevron points right (→) when collapsed = expand action
126
- :host.cc-side-nav-host-collapsed .cc-sn-chevron {
127
- transform: rotate(180deg);
128
- }
129
-
130
- // ─── Nav Container ────────────────────────────────────────────────────────────
131
-
132
- .cc-side-nav {
133
- display: flex;
134
- flex-direction: column;
135
- gap: var(--cc-side-nav-gap-sections, 24px);
136
- padding: var(--cc-side-nav-padding, 16px);
137
- width: var(--cc-side-nav-width, 220px);
138
- min-width: var(--cc-side-nav-width, 220px);
139
- box-sizing: border-box;
140
- background-color: var(--cc-side-nav-bg, #ffffff);
141
- border-right: 1px solid var(--cc-side-nav-border-color, rgba(0, 0, 0, 0.08));
142
- height: 100%;
143
- overflow-y: auto;
144
- overflow-x: hidden;
145
- transition:
146
- width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
147
- min-width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
148
- padding 0.3s cubic-bezier(0.4, 0, 0.2, 1);
149
-
150
- &::-webkit-scrollbar { width: 3px; }
151
- &::-webkit-scrollbar-track { background: transparent; }
152
- &::-webkit-scrollbar-thumb {
153
- background: rgba(0, 0, 0, 0.15);
154
- border-radius: 2px;
155
- }
156
- &::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.3); }
157
-
158
- &.collapsed {
159
- width: var(--cc-side-nav-collapsed-width, 56px);
160
- min-width: var(--cc-side-nav-collapsed-width, 56px);
161
- padding: var(--cc-side-nav-padding, 16px) 8px;
162
-
163
- .cc-side-nav-link {
164
- justify-content: center;
165
- gap: 0;
166
- padding: 10px;
167
- }
168
-
169
- .cc-side-nav-icon {
170
- font-size: 20px;
171
- }
172
- }
173
- }
174
-
175
- // ─── Section & Heading ────────────────────────────────────────────────────────
176
-
177
- .cc-side-nav-section {
178
- display: flex;
179
- flex-direction: column;
180
- gap: 12px;
181
- }
182
-
183
- .cc-side-nav-heading-row {
184
- display: flex;
185
- align-items: center;
186
- justify-content: space-between;
187
- min-height: 28px;
188
- }
189
-
190
- .cc-side-nav-heading {
191
- margin: 0;
192
- padding: 0 16px;
193
- font-family: var(--cc-side-nav-font-family, 'Poppins', sans-serif);
194
- font-weight: var(--cc-side-nav-heading-font-weight, 500);
195
- font-style: normal;
196
- font-size: var(--cc-side-nav-heading-font-size, 16px);
197
- text-transform: uppercase;
198
- color: var(--cc-side-nav-heading-color, #3C4043);
199
- flex: 1;
200
- }
201
-
202
- // ─── Nav List ─────────────────────────────────────────────────────────────────
203
-
204
- .cc-side-nav-list {
205
- list-style: none;
206
- margin: 0;
207
- padding: 0;
208
- display: flex;
209
- flex-direction: column;
210
- gap: var(--cc-side-nav-item-gap, 4px);
211
- }
212
-
213
- .cc-side-nav-list-item {
214
- margin: 0;
215
- padding: 0;
216
- }
217
-
218
- .cc-side-nav-link {
219
- display: flex;
220
- align-items: center;
221
- gap: 12px;
222
- padding: var(--cc-side-nav-item-padding, 12px 16px);
223
- text-decoration: none;
224
- cursor: pointer;
225
- border-radius: var(--cc-side-nav-item-border-radius, 8px);
226
- transition: background-color 0.2s ease, opacity 0.2s ease;
227
- font-family: var(--cc-side-nav-font-family, 'Poppins', sans-serif);
228
- font-weight: var(--cc-side-nav-item-font-weight, 400);
229
- font-style: normal;
230
- font-size: var(--cc-side-nav-item-font-size, 14px);
231
- color: var(--cc-side-nav-item-color, #5F6368);
232
-
233
- &:hover:not(.disabled) {
234
- background-color: var(--cc-side-nav-item-hover-bg, rgba(30, 30, 45, 0.08));
235
- color: var(--cc-side-nav-item-hover-color, #1e1e2d);
236
- }
237
-
238
- &.active {
239
- background: var(--cc-side-nav-active-bg, #1e1e2d);
240
- opacity: 1;
241
- border-radius: var(--cc-side-nav-item-border-radius, 8px);
242
- font-weight: var(--cc-side-nav-active-font-weight, 500);
243
- color: var(--cc-side-nav-active-color, #ffffff);
244
-
245
- &:hover {
246
- background-color: var(--cc-side-nav-active-hover-bg, #2a2a3d);
247
- color: var(--cc-side-nav-active-color, #ffffff);
248
- }
249
- }
250
-
251
- &.disabled {
252
- cursor: not-allowed;
253
- opacity: var(--cc-side-nav-disabled-opacity, 0.5);
254
- }
255
- }
256
-
257
- .cc-side-nav-icon {
258
- display: flex;
259
- align-items: center;
260
- justify-content: center;
261
- font-size: 16px;
262
- flex-shrink: 0;
263
- }
264
-
265
- // ─── Label Slide-fade on Collapse ─────────────────────────────────────────────
266
- // max-width collapses the layout space; opacity fades the text simultaneously.
267
- // Keeping the element in DOM (no *ngIf) allows smooth transition in both directions.
268
-
269
- .cc-side-nav-label {
270
- flex: 1;
271
- white-space: nowrap;
272
- overflow: hidden;
273
- max-width: 200px;
274
- opacity: 1;
275
- transition:
276
- opacity 0.15s ease,
277
- max-width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
278
- }
279
-
280
- .collapsed .cc-side-nav-label {
281
- opacity: 0;
282
- max-width: 0;
283
- }
284
-
285
- // ─── Arrow Slide-fade on Collapse ─────────────────────────────────────────────
286
-
287
- .cc-side-nav-arrow {
288
- margin-left: auto;
289
- font-size: 18px;
290
- opacity: 0.7;
291
- overflow: hidden;
292
- max-width: 30px;
293
- flex-shrink: 0;
294
- white-space: nowrap;
295
- transition:
296
- opacity 0.15s ease,
297
- max-width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
298
- }
299
-
300
- .collapsed .cc-side-nav-arrow {
301
- opacity: 0;
302
- max-width: 0;
303
- }
304
-
305
- .cc-side-nav-link.active .cc-side-nav-arrow {
306
- color: var(--cc-side-nav-active-color, #FFFFFF);
307
- opacity: 1;
308
- }
309
-
310
- // ─── Tooltip ──────────────────────────────────────────────────────────────────
311
-
312
- ::ng-deep .mat-mdc-tooltip.cc-side-nav-tooltip {
313
- margin-left: var(--cc-side-nav-tooltip-offset, 20px) !important;
314
- overflow: visible !important;
315
-
316
- .mdc-tooltip__surface {
317
- background-color: var(--cc-side-nav-tooltip-bg, #1e1e2d) !important;
318
- color: var(--cc-side-nav-tooltip-color, #FFFFFF) !important;
319
- font-family: var(--cc-side-nav-font-family, 'Poppins', sans-serif) !important;
320
- font-size: var(--cc-side-nav-tooltip-font-size, 12px) !important;
321
- font-weight: var(--cc-side-nav-tooltip-font-weight, 500) !important;
322
- padding: var(--cc-side-nav-tooltip-padding, 8px 14px) !important;
323
- border-radius: var(--cc-side-nav-tooltip-border-radius, 6px) !important;
324
- box-shadow: var(--cc-side-nav-tooltip-shadow, 0 4px 12px rgba(0, 0, 0, 0.35)) !important;
325
- letter-spacing: var(--cc-side-nav-tooltip-letter-spacing, 0.2px) !important;
326
- position: relative !important;
327
- overflow: visible !important;
328
-
329
- &::before {
330
- content: '';
331
- position: absolute;
332
- left: -6px;
333
- top: 50%;
334
- transform: translateY(-50%);
335
- width: 0;
336
- height: 0;
337
- border-top: 5px solid transparent;
338
- border-bottom: 5px solid transparent;
339
- border-right: 6px solid var(--cc-side-nav-tooltip-bg, #1e1e2d);
340
- }
341
- }
342
- }
@@ -1,135 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, HostBinding } from '@angular/core';
2
- import { TooltipPosition } from '@angular/material/tooltip';
3
- import { SideNavSection, SideNavItem, SideNavStyleConfig } from '../../side-nav.models';
4
- import { DEFAULT_SIDE_NAV_TOOLTIP_POSITION } from '../../../../utils/constants';
5
-
6
- @Component({
7
- selector: 'lib-side-nav',
8
- templateUrl: './side-nav.component.html',
9
- styleUrls: ['./side-nav.component.scss'],
10
- standalone: false
11
- })
12
- export class SideNavComponent implements OnChanges {
13
- @Input() sections: SideNavSection[] = [];
14
- @Input() userRoles?: string[]; // If provided, filters items automatically based on roles
15
- @Input() activeId?: string;
16
- @Input() styleConfig?: SideNavStyleConfig;
17
-
18
- /** Control whether the nav is collapsed externally (two-way bindable) */
19
- @Input() collapsed: boolean = false;
20
- /** Width of the nav when expanded. Overrides the CSS variable default. */
21
- @Input() width?: string;
22
- /** Width of the nav when collapsed (icons only). Overrides the CSS variable default. */
23
- @Input() collapsedWidth?: string;
24
- /** Whether to show the collapse toggle button */
25
- @Input() showCollapseToggle: boolean = true;
26
- /** Whether to hide icons when the side nav is expanded */
27
- @Input() hideIconsWhenExpanded: boolean = false;
28
- /** Whether to show tooltips on nav items */
29
- @Input() showTooltips: boolean = false;
30
- /** Position of the tooltip */
31
- @Input() tooltipPosition: TooltipPosition = DEFAULT_SIDE_NAV_TOOLTIP_POSITION as TooltipPosition;
32
-
33
- /** Optional dictionary for label translation */
34
- @Input() labels?: { [key: string]: string };
35
-
36
- @Output() itemClicked = new EventEmitter<SideNavItem>();
37
- /** Emits whenever the collapsed state changes (supports two-way binding via [(collapsed)]) */
38
- @Output() collapsedChange = new EventEmitter<boolean>();
39
-
40
- /** Applies collapsed class to :host for the width CSS transition */
41
- @HostBinding('class.cc-side-nav-host-collapsed') get isHostCollapsed() {
42
- return this.collapsed;
43
- }
44
-
45
- filteredSections: SideNavSection[] = [];
46
-
47
- ngOnChanges(changes: SimpleChanges): void {
48
- if (changes['sections'] || changes['userRoles'] || changes['labels']) {
49
- this.filterAndMapSections();
50
- }
51
- }
52
-
53
- private filterAndMapSections() {
54
- if (!this.sections) {
55
- this.filteredSections = [];
56
- return;
57
- }
58
-
59
- const clonedSections: SideNavSection[] = structuredClone(this.sections);
60
-
61
- this.filteredSections = clonedSections.map(section => {
62
- // Map section heading if labels are provided
63
- if (this.labels && section.heading) {
64
- section.heading = this.labels[section.heading] || section.heading;
65
- }
66
-
67
- // Filter and map items
68
- section.items = section.items.filter(item => {
69
- if (this.userRoles && this.userRoles.length > 0 && item.roles && item.roles.length > 0) {
70
- const hasRole = item.roles.some(role => this.userRoles?.includes(role));
71
- if (!hasRole) return false;
72
- }
73
- return true;
74
- }).map((item: any) => {
75
- // Map item labels and tooltips
76
- if (this.labels) {
77
- const mappedLabel = this.labels[item.labelKey || item.label] || item.labelKey || item.label;
78
- return {
79
- ...item,
80
- label: mappedLabel,
81
- tooltip: this.labels[item.tooltip || item.labelKey] || mappedLabel
82
- };
83
- }
84
- return item;
85
- });
86
-
87
- return section;
88
- }).filter(section => section.items.length > 0);
89
- }
90
-
91
- onItemClick(item: SideNavItem, event: Event) {
92
- if (item.disabled) {
93
- event.preventDefault();
94
- return;
95
- }
96
- this.activeId = item.id;
97
- this.itemClicked.emit(item);
98
- }
99
-
100
- toggleCollapse() {
101
- this.collapsed = !this.collapsed;
102
- this.collapsedChange.emit(this.collapsed);
103
- }
104
-
105
- get customStyles(): { [key: string]: string } {
106
- const styles: { [key: string]: string } = {};
107
-
108
- // Size overrides from direct inputs (take priority over styleConfig)
109
- if (this.width) styles['--cc-side-nav-width'] = this.width;
110
- if (this.collapsedWidth) styles['--cc-side-nav-collapsed-width'] = this.collapsedWidth;
111
-
112
- if (!this.styleConfig) return styles;
113
-
114
- if (this.styleConfig.bg) styles['--cc-side-nav-bg'] = this.styleConfig.bg;
115
- if (this.styleConfig.width) styles['--cc-side-nav-width'] = this.styleConfig.width;
116
- if (this.styleConfig.collapsedWidth) styles['--cc-side-nav-collapsed-width'] = this.styleConfig.collapsedWidth;
117
- if (this.styleConfig.fontFamily) styles['--cc-side-nav-font-family'] = this.styleConfig.fontFamily;
118
- if (this.styleConfig.headingColor) styles['--cc-side-nav-heading-color'] = this.styleConfig.headingColor;
119
- if (this.styleConfig.itemColor) styles['--cc-side-nav-item-color'] = this.styleConfig.itemColor;
120
- if (this.styleConfig.itemHoverBg) styles['--cc-side-nav-item-hover-bg'] = this.styleConfig.itemHoverBg;
121
- if (this.styleConfig.activeBg) styles['--cc-side-nav-active-bg'] = this.styleConfig.activeBg;
122
- if (this.styleConfig.activeColor) styles['--cc-side-nav-active-color'] = this.styleConfig.activeColor;
123
- if (this.styleConfig.activeHoverBg) styles['--cc-side-nav-active-hover-bg'] = this.styleConfig.activeHoverBg;
124
- if (this.styleConfig.toggleBg) styles['--cc-side-nav-toggle-bg'] = this.styleConfig.toggleBg;
125
- if (this.styleConfig.toggleBorderColor) styles['--cc-side-nav-toggle-border-color'] = this.styleConfig.toggleBorderColor;
126
- if (this.styleConfig.tooltipBg) styles['--cc-side-nav-tooltip-bg'] = this.styleConfig.tooltipBg;
127
- if (this.styleConfig.tooltipColor) styles['--cc-side-nav-tooltip-color'] = this.styleConfig.tooltipColor;
128
- if (this.styleConfig.tooltipFontWeight) styles['--cc-side-nav-tooltip-font-weight'] = this.styleConfig.tooltipFontWeight;
129
- if (this.styleConfig.tooltipLetterSpacing) styles['--cc-side-nav-tooltip-letter-spacing'] = this.styleConfig.tooltipLetterSpacing;
130
- if (this.styleConfig.tooltipOffset) styles['--cc-side-nav-tooltip-offset'] = this.styleConfig.tooltipOffset;
131
- if (this.styleConfig.tooltipShadow) styles['--cc-side-nav-tooltip-shadow'] = this.styleConfig.tooltipShadow;
132
-
133
- return styles;
134
- }
135
- }
@@ -1,38 +0,0 @@
1
- export interface SideNavItem {
2
- id: string;
3
- label: string;
4
- icon?: string;
5
- route?: string; // Optional: Angular router link path
6
- roles?: string[]; // Optional RBAC role checking
7
- disabled?: boolean;
8
- showArrow?: boolean; // Optional: Toggle to show/hide the arrow icon for this item
9
- tooltip?: string; // Optional: Custom tooltip text, defaults to label if not provided
10
- }
11
-
12
- export interface SideNavStyleConfig {
13
- bg?: string;
14
- width?: string;
15
- collapsedWidth?: string;
16
- fontFamily?: string;
17
- headingColor?: string;
18
- itemColor?: string;
19
- itemHoverBg?: string;
20
- activeBg?: string;
21
- activeColor?: string;
22
- activeHoverBg?: string;
23
- // Toggle pill
24
- toggleBg?: string;
25
- toggleBorderColor?: string;
26
- // Tooltip
27
- tooltipBg?: string;
28
- tooltipColor?: string;
29
- tooltipFontWeight?: string;
30
- tooltipLetterSpacing?: string;
31
- tooltipOffset?: string;
32
- tooltipShadow?: string;
33
- }
34
-
35
- export interface SideNavSection {
36
- heading?: string; // E.g., 'LEARNING CENTRE'. Optional if a section has no heading.
37
- items: SideNavItem[];
38
- }