@goat-bravos/intern-hub-layout 1.0.5 → 1.2.1

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.
package/README.md CHANGED
@@ -14,8 +14,14 @@ A comprehensive Angular library providing reusable layout components and shared
14
14
  - [Features](#-features)
15
15
  - [Installation](#-installation)
16
16
  - [Quick Start](#-quick-start)
17
- - [Usage Examples](#-usage-examples)
18
- - [Components API Reference](#-components-api-reference)
17
+ - [Components](#-components)
18
+ - [Layout Components](#layout-components)
19
+ - [Button Components](#button-components)
20
+ - [Input Components](#input-components)
21
+ - [Table Components](#table-components)
22
+ - [Approval Components](#approval-components)
23
+ - [Pop-up Components](#pop-up-components)
24
+ - [Icon Components](#icon-components)
19
25
  - [Development](#-development)
20
26
  - [Contributing](#-contributing)
21
27
  - [License](#-license)
@@ -24,11 +30,12 @@ A comprehensive Angular library providing reusable layout components and shared
24
30
 
25
31
  ## ✨ Features
26
32
 
27
- - 🎨 **Pre-built Layouts** - Main layout with sidebar and header components
28
- - 🧩 **Reusable UI Components** - Buttons, inputs, tables, and more
29
- - 🔧 **Highly Configurable** - Route-based configuration via Angular Router
33
+ - 🎨 **Pre-built Layouts** - Header and sidebar components with hover effects
34
+ - 🧩 **Reusable UI Components** - Buttons, inputs, tables, approval lists, and more
35
+ - 🔧 **Highly Configurable** - Extensive customization via inputs
30
36
  - 📦 **Standalone Components** - Modern Angular standalone component architecture
31
37
  - 🎯 **TypeScript Support** - Full type definitions included
38
+ - ♿ **Accessible** - Built with accessibility best practices
32
39
  - 🚀 **Angular 21 Ready** - Built for the latest Angular version
33
40
 
34
41
  ---
@@ -49,371 +56,738 @@ This library requires the following peer dependencies:
49
56
  | ----------------- | ------- | ----------- |
50
57
  | `@angular/common` | ^21.0.0 | ✅ Yes |
51
58
  | `@angular/core` | ^21.0.0 | ✅ Yes |
59
+ | `@angular/forms` | ^21.0.0 | ✅ Yes |
52
60
  | `@angular/router` | ^21.0.0 | ✅ Yes |
53
- | `dynamic-ds` | ^1.0.0 | ⚠️ Optional |
61
+ | `dynamic-ds` | ^1.0.2 | ⚠️ Optional |
54
62
 
55
63
  Install peer dependencies if not already present:
56
64
 
57
65
  ```bash
58
- npm install @angular/common @angular/core @angular/router dynamic-ds
66
+ npm install @angular/common @angular/core @angular/forms @angular/router
59
67
  ```
60
68
 
61
69
  ---
62
70
 
63
71
  ## 🚀 Quick Start
64
72
 
65
- ### Step 1: Enable Component Input Binding
73
+ ### Step 1: Import Components
66
74
 
67
- Add `withComponentInputBinding()` to your `app.config.ts` to enable route-based configuration:
75
+ Import the components you need in your Angular component:
68
76
 
69
77
  ```typescript
70
- // src/app/app.config.ts
71
- import { ApplicationConfig } from "@angular/core";
72
- import { provideRouter, withComponentInputBinding } from "@angular/router";
73
- import { routes } from "./app.routes";
74
-
75
- export const appConfig: ApplicationConfig = {
76
- providers: [provideRouter(routes, withComponentInputBinding())],
77
- };
78
+ import { Component } from "@angular/core";
79
+ import { HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextComponent } from "@goat-bravos/intern-hub-layout";
80
+
81
+ @Component({
82
+ selector: "app-root",
83
+ standalone: true,
84
+ imports: [HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextComponent],
85
+ templateUrl: "./app.component.html",
86
+ })
87
+ export class AppComponent {}
88
+ ```
89
+
90
+ ### Step 2: Use in Template
91
+
92
+ ```html
93
+ <!-- Header -->
94
+ <app-header-component [data]="headerData"></app-header-component>
95
+
96
+ <!-- Sidebar -->
97
+ <app-sidebar [data]="sidebarData"></app-sidebar>
98
+
99
+ <!-- Button -->
100
+ <app-button-container content="Click Me" size="md" backgroundColor="var(--brand-500)" (buttonClick)="onButtonClick()"></app-button-container>
101
+
102
+ <!-- Input -->
103
+ <app-input-text headerInput="Username" placeholder="Enter your username" [required]="true" [(value)]="username"></app-input-text>
78
104
  ```
79
105
 
80
- ### Step 2: Configure Routes with Layout
106
+ ---
107
+
108
+ ## 🧩 Components
109
+
110
+ ### Layout Components
111
+
112
+ #### HeaderComponent
81
113
 
82
- Set up the `MainLayoutComponent` as your app shell:
114
+ A responsive header with logo, action buttons, and user profile.
115
+
116
+ **Selector:** `app-header-component`
83
117
 
84
118
  ```typescript
85
- // src/app/app.routes.ts
86
- import { Routes } from "@angular/router";
87
- import { MainLayoutComponent } from "@goat-bravos/intern-hub-layout";
88
-
89
- export const routes: Routes = [
90
- {
91
- path: "",
92
- component: MainLayoutComponent,
93
- data: {
94
- sidebarItems: [
95
- { icon: "dsi-home-01-line", content: "Home" },
96
- { icon: "dsi-map-01-line", content: "Roadmap" },
97
- { icon: "dsi-file-01-line", content: "Documents" },
98
- ],
99
- },
100
- children: [
119
+ import { HeaderComponent, HeaderData } from "@goat-bravos/intern-hub-layout";
120
+
121
+ @Component({
122
+ imports: [HeaderComponent],
123
+ template: `<app-header-component [data]="headerData"></app-header-component>`,
124
+ })
125
+ export class MyComponent {
126
+ headerData: HeaderData = {
127
+ headerItems: [
101
128
  {
102
- path: "",
103
- loadComponent: () => import("./pages/home/home.component").then((m) => m.HomeComponent),
129
+ icon: "dsi-bell-line",
130
+ content: "Notifications",
131
+ badge: "5",
132
+ method: () => console.log("Notifications clicked"),
104
133
  },
105
134
  {
106
- path: "roadmap",
107
- loadComponent: () => import("./pages/roadmap/roadmap.component").then((m) => m.RoadmapComponent),
135
+ icon: "dsi-settings-line",
136
+ content: "Settings",
137
+ method: () => console.log("Settings clicked"),
108
138
  },
109
139
  ],
110
- },
111
- ];
140
+ userName: "John Doe",
141
+ userIcon: "dsi-user-01-line",
142
+ dropdownIcon: "dsi-arrow-down-solid",
143
+ logo: "assets/logo.png",
144
+ };
145
+ }
146
+ ```
147
+
148
+ **Interfaces:**
149
+
150
+ ```typescript
151
+ interface HeaderData {
152
+ headerItems: HeaderAction[];
153
+ userName: string;
154
+ userIcon?: IconData | string;
155
+ userIconColor?: string;
156
+ dropdownIcon?: IconData | string;
157
+ dropdownIconColor?: string;
158
+ logo?: string;
159
+ }
160
+
161
+ interface HeaderAction {
162
+ icon: IconData | string;
163
+ content: string;
164
+ method?: () => void;
165
+ badge?: string;
166
+ colorIcon?: string;
167
+ width?: string;
168
+ height?: string;
169
+ }
112
170
  ```
113
171
 
114
172
  ---
115
173
 
116
- ## 📝 Usage Examples
174
+ #### SidebarComponent
117
175
 
118
- ### Using Button Components
176
+ A collapsible sidebar with hover expansion and customizable menu items.
177
+
178
+ **Selector:** `app-sidebar`
119
179
 
120
180
  ```typescript
121
- import { Component } from "@angular/core";
122
- import { ButtonContainerComponent, LabelButtonComponent } from "@goat-bravos/intern-hub-layout";
181
+ import { SidebarComponent, SidebarData, SidebarItem } from "@goat-bravos/intern-hub-layout";
123
182
 
124
183
  @Component({
125
- selector: "app-example",
126
- standalone: true,
127
- imports: [ButtonContainerComponent, LabelButtonComponent],
184
+ imports: [SidebarComponent],
185
+ template: `<app-sidebar [data]="sidebarData"></app-sidebar>`,
186
+ })
187
+ export class MyComponent {
188
+ sidebarData: SidebarData = {
189
+ menuItems: [
190
+ {
191
+ iconLeft: "dsi-home-01-line",
192
+ content: "Dashboard",
193
+ url: "/dashboard",
194
+ colorIconLeft: "#666",
195
+ colorIconLeftHover: "#fff",
196
+ backgroundColor: "transparent",
197
+ backgroundColorHover: "#3b82f6",
198
+ },
199
+ {
200
+ iconLeft: "dsi-users-line",
201
+ content: "Users",
202
+ url: "/users",
203
+ colorIconLeft: "#666",
204
+ colorIconLeftHover: "#fff",
205
+ },
206
+ {
207
+ iconLeft: "dsi-settings-line",
208
+ content: "Settings",
209
+ url: "/settings",
210
+ },
211
+ ],
212
+ backgroundColor: "#1e293b",
213
+ };
214
+ }
215
+ ```
216
+
217
+ **Interface:**
218
+
219
+ ```typescript
220
+ interface SidebarItem {
221
+ iconLeft?: IconData | string;
222
+ iconRight?: IconData | string;
223
+ content: string;
224
+ url?: string;
225
+ colorIconLeft?: string;
226
+ colorIconLeftHover?: string;
227
+ colorIconRight?: string;
228
+ colorIconRightHover?: string;
229
+ colorContent?: string;
230
+ colorContentHover?: string;
231
+ backgroundColor?: string;
232
+ backgroundColorHover?: string;
233
+ borderRadius?: string;
234
+ borderRadiusHover?: string;
235
+ width?: string;
236
+ height?: string;
237
+ }
238
+
239
+ interface SidebarData {
240
+ menuItems: SidebarItem[];
241
+ backgroundColor?: string;
242
+ }
243
+ ```
244
+
245
+ ---
246
+
247
+ ### Button Components
248
+
249
+ #### ButtonContainerComponent
250
+
251
+ A customizable button with icon support and multiple size variants.
252
+
253
+ **Selector:** `app-button-container`
254
+
255
+ ```typescript
256
+ import { ButtonContainerComponent, ButtonSize } from "@goat-bravos/intern-hub-layout";
257
+
258
+ @Component({
259
+ imports: [ButtonContainerComponent],
128
260
  template: `
129
- <app-button-container content="Primary Action" size="lg" backgroundColor="var(--brand-500)" (buttonClick)="onAction()"> </app-button-container>
261
+ <!-- Basic button -->
262
+ <app-button-container content="Submit" size="md" (buttonClick)="onSubmit()"></app-button-container>
263
+
264
+ <!-- Button with icons -->
265
+ <app-button-container content="Download" size="lg" leftIcon="⬇" backgroundColor="#10b981" color="#ffffff" (buttonClick)="onDownload()"></app-button-container>
130
266
 
131
- <app-label-button label="Status: Active" bgColor="#22c55e" textColor="#ffffff"> </app-label-button>
267
+ <!-- Small button -->
268
+ <app-button-container content="Edit" size="xs" backgroundColor="#f59e0b" (buttonClick)="onEdit()"></app-button-container>
132
269
  `,
133
270
  })
134
- export class ExampleComponent {
135
- onAction() {
136
- console.log("Button clicked!");
271
+ export class MyComponent {
272
+ onSubmit() {
273
+ console.log("Form submitted");
274
+ }
275
+ onDownload() {
276
+ console.log("Download initiated");
277
+ }
278
+ onEdit() {
279
+ console.log("Edit clicked");
137
280
  }
138
281
  }
139
282
  ```
140
283
 
141
- ### Using Input Components
284
+ **Inputs:**
285
+
286
+ | Input | Type | Default | Description |
287
+ | ----------------- | ------------------------------ | ---------------------- | --------------------- |
288
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Button size variant |
289
+ | `content` | `string` | `''` | Button text |
290
+ | `leftIcon` | `string` | - | Left icon text/class |
291
+ | `rightIcon` | `string` | - | Right icon text/class |
292
+ | `color` | `string` | `'var(--brand-100)'` | Text color |
293
+ | `backgroundColor` | `string` | `'var(--utility-900)'` | Background color |
294
+ | `borderColor` | `string` | `'var(--brand-100)'` | Border color |
295
+ | `fontSize` | `string` | - | Custom font size |
296
+
297
+ **Outputs:**
298
+
299
+ | Output | Type | Description |
300
+ | ------------- | ------------------- | ------------------------- |
301
+ | `buttonClick` | `EventEmitter<any>` | Emits when button clicked |
302
+
303
+ ---
304
+
305
+ #### LabelButtonComponent
306
+
307
+ A simple label/badge style button for status indicators.
308
+
309
+ **Selector:** `app-label-button`
142
310
 
143
311
  ```typescript
144
- import { Component } from "@angular/core";
145
- import { InputTextComponent, InputCalendarComponent } from "@goat-bravos/intern-hub-layout";
312
+ import { LabelButtonComponent } from "@goat-bravos/intern-hub-layout";
146
313
 
147
314
  @Component({
148
- selector: "app-form-example",
149
- standalone: true,
150
- imports: [InputTextComponent, InputCalendarComponent],
315
+ imports: [LabelButtonComponent],
316
+ template: `
317
+ <!-- Success status -->
318
+ <app-label-button label="Active" bgColor="#22c55e" textColor="#ffffff"></app-label-button>
319
+
320
+ <!-- Warning status -->
321
+ <app-label-button label="Pending" bgColor="#f59e0b" textColor="#000000"></app-label-button>
322
+
323
+ <!-- Custom size -->
324
+ <app-label-button label="Custom" bgColor="#3b82f6" width="120px" height="32px"></app-label-button>
325
+ `,
326
+ })
327
+ export class MyComponent {}
328
+ ```
329
+
330
+ **Inputs:**
331
+
332
+ | Input | Type | Default | Description |
333
+ | ------------- | -------- | ---------------------- | ---------------- |
334
+ | `label` | `string` | `''` | Button text |
335
+ | `bgColor` | `string` | `''` | Background color |
336
+ | `borderColor` | `string` | `''` | Border color |
337
+ | `textColor` | `string` | `'var(--neutral-100)'` | Text color |
338
+ | `width` | `string` | `'100%'` | Button width |
339
+ | `height` | `string` | `'28px'` | Button height |
340
+
341
+ ---
342
+
343
+ ### Input Components
344
+
345
+ #### InputTextComponent
346
+
347
+ A text input with label, character limit, and icon support.
348
+
349
+ **Selector:** `app-input-text`
350
+
351
+ ```typescript
352
+ import { InputTextComponent } from "@goat-bravos/intern-hub-layout";
353
+
354
+ @Component({
355
+ imports: [InputTextComponent],
151
356
  template: `
152
- <app-input-text headerInput="Username" placeholder="Enter username" [required]="true" [maxLength]="50" [showLimit]="true" [(value)]="username" (valueChange)="onUsernameChange($event)"> </app-input-text>
357
+ <!-- Basic input -->
358
+ <app-input-text headerInput="Email" placeholder="Enter your email" [required]="true" [(value)]="email" (valueChange)="onEmailChange($event)"></app-input-text>
359
+
360
+ <!-- Input with character limit -->
361
+ <app-input-text headerInput="Bio" placeholder="Tell us about yourself" [maxLength]="200" [showLimit]="true" [(value)]="bio"></app-input-text>
153
362
 
154
- <app-input-calendar headerInput="Start Date" placeholder="dd/mm/yyyy" [(value)]="startDate"> </app-input-calendar>
363
+ <!-- Password input with icon -->
364
+ <app-input-text headerInput="Password" placeholder="Enter password" typeInput="password" icon="dsi-eye-line" (iconClick)="togglePassword()" [(value)]="password"></app-input-text>
155
365
  `,
156
366
  })
157
- export class FormExampleComponent {
158
- username = "";
159
- startDate = "";
367
+ export class MyComponent {
368
+ email = "";
369
+ bio = "";
370
+ password = "";
160
371
 
161
- onUsernameChange(value: string) {
162
- console.log("Username:", value);
372
+ onEmailChange(value: string) {
373
+ console.log("Email changed:", value);
374
+ }
375
+
376
+ togglePassword() {
377
+ // Toggle password visibility
163
378
  }
164
379
  }
165
380
  ```
166
381
 
167
- ### Using Table Components
382
+ **Inputs:**
383
+
384
+ | Input | Type | Default | Description |
385
+ | ------------- | --------- | -------- | ------------------------------ |
386
+ | `headerInput` | `string` | `''` | Label text above input |
387
+ | `placeholder` | `string` | `''` | Placeholder text |
388
+ | `value` | `string` | `''` | Input value (two-way binding) |
389
+ | `readonly` | `boolean` | `false` | Read-only state |
390
+ | `required` | `boolean` | `false` | Shows required indicator (\*) |
391
+ | `width` | `string` | `'100%'` | Container width |
392
+ | `maxLength` | `number` | `0` | Max characters (0 = unlimited) |
393
+ | `showLimit` | `boolean` | `false` | Show character count |
394
+ | `icon` | `string` | `''` | Icon class for input |
395
+ | `typeInput` | `string` | `'text'` | Input type |
396
+
397
+ **Outputs:**
398
+
399
+ | Output | Type | Description |
400
+ | ------------- | ---------------------- | -------------------------- |
401
+ | `valueChange` | `EventEmitter<string>` | Emits on value change |
402
+ | `iconClick` | `EventEmitter<void>` | Emits when icon is clicked |
403
+
404
+ ---
405
+
406
+ #### InputStepperComponent
407
+
408
+ A numeric stepper input with increment/decrement buttons.
409
+
410
+ **Selector:** `app-input-stepper`
411
+
412
+ ```typescript
413
+ import { InputStepperComponent } from "@goat-bravos/intern-hub-layout";
414
+
415
+ @Component({
416
+ imports: [InputStepperComponent],
417
+ template: `
418
+ <!-- Basic stepper -->
419
+ <app-input-stepper headerInput="Quantity" [(value)]="quantity" [min]="1" [max]="100" [step]="1"></app-input-stepper>
420
+
421
+ <!-- Stepper with helper text -->
422
+ <app-input-stepper headerInput="Age" [(value)]="age" [min]="0" [max]="120" helperText="Enter your age" [required]="true"></app-input-stepper>
423
+
424
+ <!-- Disabled stepper -->
425
+ <app-input-stepper headerInput="Fixed Value" [value]="10" [disabled]="true"></app-input-stepper>
426
+ `,
427
+ })
428
+ export class MyComponent {
429
+ quantity = 1;
430
+ age = 25;
431
+ }
432
+ ```
433
+
434
+ **Inputs:**
435
+
436
+ | Input | Type | Default | Description |
437
+ | ------------- | --------------------------------------- | ----------- | ----------------- |
438
+ | `headerInput` | `string` | `''` | Label text |
439
+ | `value` | `number` | `0` | Current value |
440
+ | `min` | `number` | `0` | Minimum value |
441
+ | `max` | `number` | `100` | Maximum value |
442
+ | `step` | `number` | `1` | Step increment |
443
+ | `placeholder` | `string` | `''` | Input placeholder |
444
+ | `readonly` | `boolean` | `false` | Read-only state |
445
+ | `required` | `boolean` | `false` | Required state |
446
+ | `disabled` | `boolean` | `false` | Disabled state |
447
+ | `width` | `string` | `'100%'` | Component width |
448
+ | `error` | `string` | `''` | Error message |
449
+ | `helperText` | `string` | `''` | Helper text below |
450
+ | `state` | `'default' \| 'negative' \| 'positive'` | `'default'` | Visual state |
451
+
452
+ **Outputs:**
453
+
454
+ | Output | Type | Description |
455
+ | ------------- | ---------------------- | --------------------- |
456
+ | `valueChange` | `EventEmitter<number>` | Emits on value change |
457
+
458
+ ---
459
+
460
+ #### InputCalendarComponent
461
+
462
+ A date picker with auto-formatting (dd/mm/yyyy) and validation.
463
+
464
+ **Selector:** `app-input-calendar`
465
+
466
+ ```typescript
467
+ import { InputCalendarComponent } from "@goat-bravos/intern-hub-layout";
468
+
469
+ @Component({
470
+ imports: [InputCalendarComponent],
471
+ template: `
472
+ <!-- Basic date picker -->
473
+ <app-input-calendar headerInput="Start Date" [(value)]="startDate" (valueChange)="onDateChange($event)"></app-input-calendar>
474
+
475
+ <!-- Required date picker -->
476
+ <app-input-calendar headerInput="Birth Date" [required]="true" [(value)]="birthDate"></app-input-calendar>
477
+
478
+ <!-- Read-only date -->
479
+ <app-input-calendar headerInput="Created At" [readonly]="true" [value]="createdAt"></app-input-calendar>
480
+ `,
481
+ })
482
+ export class MyComponent {
483
+ startDate = ""; // ISO format: '2024-01-15'
484
+ birthDate = "";
485
+ createdAt = "2024-01-01";
486
+
487
+ onDateChange(isoDate: string) {
488
+ console.log("Date selected:", isoDate); // Output: '2024-01-15'
489
+ }
490
+ }
491
+ ```
492
+
493
+ **Inputs:**
494
+
495
+ | Input | Type | Default | Description |
496
+ | ------------- | --------- | -------------- | ----------------------------------- |
497
+ | `headerInput` | `string` | `''` | Label text |
498
+ | `value` | `string` | `''` | Date value (ISO format: yyyy-mm-dd) |
499
+ | `placeholder` | `string` | `'dd/mm/yyyy'` | Placeholder text |
500
+ | `readonly` | `boolean` | `false` | Read-only state |
501
+ | `required` | `boolean` | `false` | Required state |
502
+ | `width` | `string` | `'100%'` | Component width |
503
+
504
+ **Outputs:**
505
+
506
+ | Output | Type | Description |
507
+ | ------------- | ---------------------- | --------------------------------- |
508
+ | `valueChange` | `EventEmitter<string>` | Emits ISO date on valid selection |
509
+
510
+ > **Note:** The calendar validates dates and only emits valid dates. Invalid dates like `31/02/2024` will not trigger a valueChange event.
511
+
512
+ ---
513
+
514
+ ### Table Components
515
+
516
+ #### TableHeaderComponent & TableBodyComponent
517
+
518
+ Table components with customizable columns and template support.
519
+
520
+ **Selectors:** `tr[app-table-header]`, `tbody[app-table-body]`
168
521
 
169
522
  ```typescript
170
- import { Component } from "@angular/core";
171
523
  import { TableHeaderComponent, TableBodyComponent, ColumnConfig } from "@goat-bravos/intern-hub-layout";
524
+ import { CommonModule } from "@angular/common";
172
525
 
173
526
  @Component({
174
- selector: "app-table-example",
175
- standalone: true,
176
- imports: [TableHeaderComponent, TableBodyComponent],
527
+ imports: [CommonModule, TableHeaderComponent, TableBodyComponent],
177
528
  template: `
178
- <table>
529
+ <table class="data-table">
179
530
  <thead>
180
531
  <tr app-table-header [columns]="columns" backgroundColor="#1e293b" textColor="#ffffff"></tr>
181
532
  </thead>
182
- <tbody app-table-body [columns]="columns" [rows]="data"></tbody>
533
+ <tbody app-table-body [columns]="columns" [rows]="users" [columnTemplates]="{ status: statusTemplate }"></tbody>
183
534
  </table>
535
+
536
+ <!-- Custom template for status column -->
537
+ <ng-template #statusTemplate let-value let-row="row">
538
+ <app-label-button [label]="value" [bgColor]="value === 'Active' ? '#22c55e' : '#ef4444'" textColor="#ffffff"></app-label-button>
539
+ </ng-template>
184
540
  `,
185
541
  })
186
- export class TableExampleComponent {
542
+ export class MyComponent {
187
543
  columns: ColumnConfig[] = [
188
544
  { header: "ID", key: "id", width: "80px" },
189
545
  { header: "Name", key: "name", width: "200px" },
546
+ { header: "Email", key: "email", width: "250px" },
190
547
  { header: "Status", key: "status", width: "120px" },
191
548
  ];
192
549
 
193
- data = [
194
- { id: 1, name: "John Doe", status: "Active" },
195
- { id: 2, name: "Jane Smith", status: "Pending" },
550
+ users = [
551
+ { id: 1, name: "John Doe", email: "john@example.com", status: "Active" },
552
+ { id: 2, name: "Jane Smith", email: "jane@example.com", status: "Inactive" },
553
+ { id: 3, name: "Bob Wilson", email: "bob@example.com", status: "Active" },
196
554
  ];
197
555
  }
198
556
  ```
199
557
 
200
- ---
201
-
202
- ## 📚 Components API Reference
203
-
204
- ### Layout Components
205
-
206
- #### `MainLayoutComponent`
207
-
208
- The main application shell with integrated sidebar and header.
209
-
210
- | Selector | `app-main-layout` |
211
- | -------------- | -------------------------------------------- |
212
- | **Inputs** | |
213
- | `sidebarItems` | `SidebarItem[]` - List of sidebar menu items |
558
+ **ColumnConfig Interface:**
214
559
 
215
560
  ```typescript
216
- interface SidebarItem {
217
- icon: string; // Icon class name (e.g., 'dsi-home-01-line')
218
- content: string; // Display text for the menu item
561
+ interface ColumnConfig {
562
+ header: string; // Display header text
563
+ key: string; // Property key in data object
564
+ width: string; // Column width (CSS value)
219
565
  }
220
566
  ```
221
567
 
222
- ---
568
+ **TableHeaderComponent Inputs:**
223
569
 
224
- #### `SidebarComponent`
570
+ | Input | Type | Default | Description |
571
+ | ----------------- | ---------------- | ------------------ | ---------------------- |
572
+ | `columns` | `ColumnConfig[]` | `[]` | Column definitions |
573
+ | `backgroundColor` | `string` | - | Header background |
574
+ | `textColor` | `string` | `'#ffffff'` | Text color |
575
+ | `headerIconLeft` | `string` | - | Left icon for columns |
576
+ | `headerIconRight` | `string` | - | Right icon for columns |
577
+ | `fontSize` | `string` | `'var(--font-xs)'` | Font size |
225
578
 
226
- Standalone sidebar navigation component.
579
+ **TableBodyComponent Inputs:**
227
580
 
228
- | Selector | `app-sidebar` |
229
- | ----------- | ----------------------------------------------- |
230
- | **Inputs** | |
231
- | `menuItems` | `SidebarItem[]` - List of menu items to display |
581
+ | Input | Type | Default | Description |
582
+ | ----------------- | ------------------------------------- | ------------------ | --------------------- |
583
+ | `rows` | `any[]` | `[]` | Data array |
584
+ | `columns` | `ColumnConfig[]` | `[]` | Column definitions |
585
+ | `columnTemplates` | `{ [key: string]: TemplateRef<any> }` | `{}` | Custom cell templates |
586
+ | `fontSize` | `string` | `'var(--font-sm)'` | Font size |
232
587
 
233
588
  ---
234
589
 
235
- #### `HeaderComponent`
590
+ ### Approval Components
236
591
 
237
- Standalone header component.
592
+ #### ApprovalListComponent
238
593
 
239
- | Selector | `app-header` |
240
- | -------- | ------------ |
594
+ A list component for displaying approval workflows with customizable right-side templates.
241
595
 
242
- ---
596
+ **Selector:** `app-approval-list`
243
597
 
244
- ### Button Components
598
+ ```typescript
599
+ import { ApprovalListComponent, ApprovalListItemInterface, ButtonContainerComponent } from "@goat-bravos/intern-hub-layout";
600
+ import { CommonModule } from "@angular/common";
245
601
 
246
- #### `ButtonContainerComponent`
602
+ @Component({
603
+ imports: [CommonModule, ApprovalListComponent, ButtonContainerComponent],
604
+ template: `
605
+ <app-approval-list [rows]="approvalItems" headerContentLeft="Applicant" headerContentRight="Actions" width="600px"></app-approval-list>
606
+
607
+ <!-- Template for action buttons -->
608
+ <ng-template #actionsTemplate let-row="row">
609
+ <div class="action-buttons">
610
+ <app-button-container content="Approve" size="xs" backgroundColor="#22c55e" (buttonClick)="approve(row)"></app-button-container>
611
+ <app-button-container content="Reject" size="xs" backgroundColor="#ef4444" (buttonClick)="reject(row)"></app-button-container>
612
+ </div>
613
+ </ng-template>
614
+ `,
615
+ })
616
+ export class MyComponent {
617
+ @ViewChild("actionsTemplate") actionsTemplate!: TemplateRef<any>;
247
618
 
248
- Customizable button with icon support.
619
+ approvalItems: ApprovalListItemInterface[] = [];
249
620
 
250
- | Selector | `app-button-container` |
251
- | ----------------- | -------------------------------------------------------------- |
252
- | **Inputs** | |
253
- | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` - Button size (default: `'md'`) |
254
- | `content` | `string` - Button text |
255
- | `leftIcon` | `string` - Left icon class |
256
- | `rightIcon` | `string` - Right icon class |
257
- | `color` | `string` - Text color (default: `var(--brand-100)`) |
258
- | `backgroundColor` | `string` - Background color (default: `var(--utility-900)`) |
259
- | `borderColor` | `string` - Border color (default: `var(--brand-100)`) |
260
- | `fontSize` | `string` - Custom font size |
261
- | **Outputs** | |
262
- | `buttonClick` | `EventEmitter<any>` - Fires when button is clicked |
621
+ ngAfterViewInit() {
622
+ this.approvalItems = [
623
+ {
624
+ name: "John Doe - Leave Request",
625
+ date: new Date("2024-01-15"),
626
+ rightTemplate: this.actionsTemplate,
627
+ rightContext: { row: { id: 1, type: "leave" } },
628
+ },
629
+ {
630
+ name: "Jane Smith - Expense Report",
631
+ date: new Date("2024-01-14"),
632
+ rightTemplate: this.actionsTemplate,
633
+ rightContext: { row: { id: 2, type: "expense" } },
634
+ },
635
+ ];
636
+ }
263
637
 
264
- ---
638
+ approve(row: any) {
639
+ console.log("Approved:", row);
640
+ }
265
641
 
266
- #### `LabelButtonComponent`
642
+ reject(row: any) {
643
+ console.log("Rejected:", row);
644
+ }
645
+ }
646
+ ```
267
647
 
268
- Small label/badge style button.
648
+ **ApprovalListItemInterface:**
269
649
 
270
- | Selector | `app-label-button` |
271
- | ------------- | --------------------------------------------- |
272
- | **Inputs** | |
273
- | `label` | `string` - Display text |
274
- | `bgColor` | `string` - Background color |
275
- | `borderColor` | `string` - Border color |
276
- | `textColor` | `string` - Text color |
277
- | `width` | `string` - Component width (default: `100%`) |
278
- | `height` | `string` - Component height (default: `28px`) |
650
+ ```typescript
651
+ interface ApprovalListItemInterface {
652
+ name: string;
653
+ date: Date;
654
+ rightTemplate?: TemplateRef<any>;
655
+ rightContext?: any;
656
+ }
657
+ ```
279
658
 
280
659
  ---
281
660
 
282
- ### Input Components
283
-
284
- #### `InputTextComponent`
285
-
286
- Standard text input with label and validation support.
287
-
288
- | Selector | `app-input-text` |
289
- | ------------- | ------------------------------------------------- |
290
- | **Inputs** | |
291
- | `headerInput` | `string` - Label text above input |
292
- | `placeholder` | `string` - Placeholder text |
293
- | `value` | `string` - Input value (two-way binding) |
294
- | `readonly` | `boolean` - Read-only state |
295
- | `required` | `boolean` - Shows required indicator |
296
- | `width` | `string` - Container width (default: `100%`) |
297
- | `maxLength` | `number` - Maximum characters (0 = unlimited) |
298
- | `showLimit` | `boolean` - Show character count |
299
- | `icon` | `string` - Icon class for input |
300
- | `typeInput` | `string` - Input type (default: `'text'`) |
301
- | **Outputs** | |
302
- | `valueChange` | `EventEmitter<string>` - Fires on value change |
303
- | `iconClick` | `EventEmitter<void>` - Fires when icon is clicked |
661
+ ### Pop-up Components
304
662
 
305
- ---
663
+ #### PopUpConfirmComponent
306
664
 
307
- #### `InputStepperComponent`
308
-
309
- Numeric input with increment/decrement controls.
310
-
311
- | Selector | `app-input-stepper` |
312
- | ------------- | ------------------------------------------------------ |
313
- | **Inputs** | |
314
- | `headerInput` | `string` - Label text |
315
- | `value` | `number` - Current value |
316
- | `min` | `number` - Minimum value (default: `0`) |
317
- | `max` | `number` - Maximum value (default: `100`) |
318
- | `step` | `number` - Step increment (default: `1`) |
319
- | `state` | `'default' \| 'negative' \| 'positive'` - Visual state |
320
- | `helperText` | `string` - Helper text below input |
321
- | `readonly` | `boolean` - Read-only state |
322
- | `required` | `boolean` - Required state |
323
- | `disabled` | `boolean` - Disabled state |
324
- | `width` | `string` - Component width |
325
- | **Outputs** | |
326
- | `valueChange` | `EventEmitter<number>` - Fires on value change |
665
+ An accessible confirmation modal dialog.
327
666
 
328
- ---
667
+ **Selector:** `app-pop-up-confirm`
329
668
 
330
- #### `InputCalendarComponent`
669
+ ```typescript
670
+ import { PopUpConfirmComponent } from "@goat-bravos/intern-hub-layout";
671
+ import { CommonModule } from "@angular/common";
331
672
 
332
- Date picker input component.
673
+ @Component({
674
+ imports: [CommonModule, PopUpConfirmComponent],
675
+ template: `
676
+ <button (click)="showConfirm = true">Delete Item</button>
333
677
 
334
- | Selector | `app-input-calendar` |
335
- | ------------- | ------------------------------------------------ |
336
- | **Inputs** | |
337
- | `headerInput` | `string` - Label text |
338
- | `value` | `string` - Date value (ISO format: `yyyy-mm-dd`) |
339
- | `placeholder` | `string` - Placeholder (default: `'dd/mm/yyyy'`) |
340
- | `readonly` | `boolean` - Read-only state |
341
- | `required` | `boolean` - Required state |
342
- | `width` | `string` - Component width |
343
- | **Outputs** | |
344
- | `valueChange` | `EventEmitter<string>` - Fires on date selection |
678
+ @if (showConfirm) {
679
+ <app-pop-up-confirm title="Confirm Delete" content="Are you sure you want to delete this item? This action cannot be undone." imgUrl="assets/warning-icon.svg" colorButton="#ef4444" (confirmClick)="onConfirm()" (cancelClick)="onCancel()"></app-pop-up-confirm>
680
+ }
681
+ `,
682
+ })
683
+ export class MyComponent {
684
+ showConfirm = false;
345
685
 
346
- ---
686
+ onConfirm() {
687
+ console.log("Confirmed!");
688
+ this.showConfirm = false;
689
+ // Perform delete action
690
+ }
347
691
 
348
- ### Table Components
692
+ onCancel() {
693
+ console.log("Cancelled");
694
+ this.showConfirm = false;
695
+ }
696
+ }
697
+ ```
349
698
 
350
- #### `TableHeaderComponent`
699
+ **Inputs:**
351
700
 
352
- Table header row component.
701
+ | Input | Type | Default | Description |
702
+ | ------------- | -------- | -------------------- | -------------------- |
703
+ | `title` | `string` | `''` | Modal title |
704
+ | `content` | `string` | `''` | Message content |
705
+ | `imgUrl` | `string` | `''` | Icon/image URL |
706
+ | `colorButton` | `string` | `'var(--brand-600)'` | Confirm button color |
353
707
 
354
- | Selector | `tr[app-table-header]` (Attribute selector) |
355
- | ----------------- | ------------------------------------------------ |
356
- | **Inputs** | |
357
- | `columns` | `ColumnConfig[]` - Column definitions |
358
- | `backgroundColor` | `string` - Header background |
359
- | `textColor` | `string` - Text color (default: `#ffffff`) |
360
- | `headerIconLeft` | `string` - Left icon for headers |
361
- | `headerIconRight` | `string` - Right icon for headers |
362
- | `fontSize` | `string` - Font size (default: `var(--font-xs)`) |
708
+ **Outputs:**
363
709
 
364
- ```typescript
365
- interface ColumnConfig {
366
- header: string; // Display text
367
- key: string; // Data property key
368
- width: string; // CSS width value
369
- }
370
- ```
710
+ | Output | Type | Description |
711
+ | -------------- | -------------------- | ---------------------- |
712
+ | `confirmClick` | `EventEmitter<void>` | Emits on confirm click |
713
+ | `cancelClick` | `EventEmitter<void>` | Emits on cancel click |
371
714
 
372
715
  ---
373
716
 
374
- #### `TableBodyComponent`
717
+ ### Icon Components
375
718
 
376
- Table body component with template support.
719
+ #### IconComponent
377
720
 
378
- | Selector | `tbody[app-table-body]` (Attribute selector) |
379
- | ----------------- | ----------------------------------------------------- |
380
- | **Inputs** | |
381
- | `rows` | `any[]` - Data array |
382
- | `columns` | `ColumnConfig[]` - Column definitions |
383
- | `columnTemplates` | `Record<string, TemplateRef>` - Custom cell templates |
721
+ A flexible icon component supporting icon libraries and custom styling.
384
722
 
385
- ---
723
+ **Selector:** `app-icon`
386
724
 
387
- ### Other Components
725
+ ```typescript
726
+ import { IconComponent, IconData } from "@goat-bravos/intern-hub-layout";
388
727
 
389
- #### `ApprovalListComponent`
728
+ @Component({
729
+ imports: [IconComponent],
730
+ template: `
731
+ <!-- Using IconData object -->
732
+ <app-icon [iconData]="settingsIcon"></app-icon>
390
733
 
391
- List component for approval workflows.
734
+ <!-- Using individual inputs -->
735
+ <app-icon icon="dsi-home-01-line" colorIcon="#3b82f6" width="24px" height="24px" (clicked)="onIconClick()"></app-icon>
736
+ `,
737
+ })
738
+ export class MyComponent {
739
+ settingsIcon: IconData = {
740
+ icon: "dsi-settings-line",
741
+ colorIcon: "#666666",
742
+ width: "20px",
743
+ height: "20px",
744
+ routerLink: "/settings",
745
+ };
746
+
747
+ onIconClick() {
748
+ console.log("Icon clicked");
749
+ }
750
+ }
751
+ ```
392
752
 
393
- | Selector | `app-approval-list` |
394
- | -------------------- | ------------------------------------------ |
395
- | **Inputs** | |
396
- | `rows` | `ApprovalListItemInterface[]` - List items |
397
- | `headerContentLeft` | `string` - Left header text |
398
- | `headerContentRight` | `string` - Right header text |
399
- | `width` | `string` - Component width |
753
+ **IconData Interface:**
754
+
755
+ ```typescript
756
+ interface IconData {
757
+ icon: string;
758
+ colorIcon?: string;
759
+ routerLink?: string;
760
+ width?: string;
761
+ height?: string;
762
+ }
763
+ ```
400
764
 
401
765
  ---
402
766
 
403
- #### `PopUpConfirmComponent`
767
+ #### FunctionalLabelComponent
768
+
769
+ A label component with icons and hover effects, commonly used in sidebars.
404
770
 
405
- Confirmation modal dialog.
771
+ **Selector:** `app-functional-label`
406
772
 
407
- | Selector | `app-pop-up-confirm` |
408
- | -------------- | --------------------------------- |
409
- | **Inputs** | |
410
- | `title` | `string` - Modal title |
411
- | `content` | `string` - Message content |
412
- | `imgUrl` | `string` - Icon/image URL |
413
- | `colorButton` | `string` - Confirm button color |
414
- | **Outputs** | |
415
- | `confirmClick` | `EventEmitter` - Fires on confirm |
416
- | `cancelClick` | `EventEmitter` - Fires on cancel |
773
+ ```typescript
774
+ import { FunctionalLabelComponent, IconData } from "@goat-bravos/intern-hub-layout";
775
+
776
+ @Component({
777
+ imports: [FunctionalLabelComponent],
778
+ template: ` <app-functional-label content="Dashboard" [iconLeft]="dashboardIcon" routerLink="/dashboard" backgroundColor="transparent" backgroundColorHover="#3b82f6" colorContent="#666" colorContentHover="#fff" (clicked)="onLabelClick($event)"></app-functional-label> `,
779
+ })
780
+ export class MyComponent {
781
+ dashboardIcon: IconData = {
782
+ icon: "dsi-home-01-line",
783
+ colorIcon: "#666",
784
+ };
785
+
786
+ onLabelClick(event: Event) {
787
+ console.log("Label clicked", event);
788
+ }
789
+ }
790
+ ```
417
791
 
418
792
  ---
419
793
 
@@ -454,19 +828,20 @@ npm run publish:lib
454
828
  intern-hub-fe-layout/
455
829
  ├── src/
456
830
  │ ├── libs/
457
- │ │ ├── layouts/ # Layout components
458
- │ │ │ ├── main-layout/
459
- │ │ │ ├── sidebar/
460
- │ │ │ └── header/
831
+ │ │ ├── layouts/ # Layout components
832
+ │ │ │ ├── header/ # Header component
833
+ │ │ │ └── sidebar/ # Sidebar component
461
834
  │ │ └── shared/
462
- │ │ └── components/ # Shared UI components
463
- │ │ ├── button/
464
- │ │ ├── input/
465
- │ │ ├── table/
466
- │ │ ├── approval/
467
- │ │ └── pop-up/
468
- └── public-api.ts # Public exports
469
- ├── ng-package.json # ng-packagr config
835
+ │ │ └── components/ # Shared UI components
836
+ │ │ ├── button/ # Button components
837
+ │ │ ├── input/ # Input components
838
+ │ │ ├── table/ # Table components
839
+ │ │ ├── approval/ # Approval list components
840
+ │ │ ├── pop-up/ # Pop-up/modal components
841
+ │ ├── icon/ # Icon component
842
+ │ │ └── functional-label/
843
+ │ └── public-api.ts # Public exports
844
+ ├── ng-package.json # ng-packagr config
470
845
  ├── package.json
471
846
  └── README.md
472
847
  ```