@goat-bravos/intern-hub-layout 4.0.0 → 4.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.
package/README.md CHANGED
@@ -4,9 +4,8 @@
4
4
  ![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?style=flat&logo=typescript&logoColor=white)
5
5
  ![License](https://img.shields.io/badge/License-MIT-green?style=flat)
6
6
  ![npm](https://img.shields.io/badge/npm-@goat--bravos/intern--hub--layout-CB3837?style=flat&logo=npm)
7
- ![Version](https://img.shields.io/badge/version-3.0.15-blue?style=flat)
8
7
 
9
- A comprehensive Angular library providing reusable layout components and shared UI elements for Intern Hub applications. Built with Angular 21, TypeScript 5.9, and designed for seamless integration with modern Angular projects.
8
+ A comprehensive Angular library providing reusable layout components and shared UI elements for Intern Hub applications. Built with Angular 21 and designed for seamless integration.
10
9
 
11
10
  ---
12
11
 
@@ -15,42 +14,29 @@ A comprehensive Angular library providing reusable layout components and shared
15
14
  - [Features](#-features)
16
15
  - [Installation](#-installation)
17
16
  - [Quick Start](#-quick-start)
18
- - [Project Structure](#-project-structure)
19
17
  - [Components](#-components)
20
18
  - [Layout Components](#layout-components)
21
19
  - [Button Components](#button-components)
22
20
  - [Input Components](#input-components)
23
- - [Date Picker Components](#date-picker-components)
24
21
  - [Table Components](#table-components)
25
22
  - [Approval Components](#approval-components)
26
- - [Modal Components](#modal-components)
27
23
  - [Pop-up Components](#pop-up-components)
28
- - [Upload Components](#upload-components)
29
24
  - [Icon Components](#icon-components)
30
- - [Best Practices](#-best-practices)
31
- - [Troubleshooting](#-troubleshooting)
32
- - [Development](#️-development)
25
+ - [Development](#-development)
33
26
  - [Contributing](#-contributing)
34
- - [Changelog](#-changelog)
35
27
  - [License](#-license)
36
- - [Links & Resources](#-links--resources)
37
- - [Support](#-support)
38
- - [Acknowledgments](#-acknowledgments)
39
28
 
40
29
  ---
41
30
 
42
31
  ## ✨ Features
43
32
 
44
- - 🎨 **Pre-built Layouts** - Header and sidebar components with smooth hover effects and animations
45
- - 🧩 **Reusable UI Components** - Buttons, inputs, tables, modals, file uploads, approval lists, and more
46
- - 🔧 **Highly Configurable** - Extensive customization via input properties and CSS custom properties
47
- - 📦 **Standalone Components** - Modern Angular standalone component architecture (no NgModules required)
48
- - 🎯 **TypeScript Support** - Full type definitions and interfaces included
49
- - ♿ **Accessible** - Built with accessibility best practices (ARIA attributes, keyboard navigation)
50
- - 🚀 **Angular 21 Ready** - Built for the latest Angular version with Signal support
51
- - 🎭 **Theme Support** - Customizable color schemes using CSS variables
52
- - 📱 **Responsive** - Mobile-first design with responsive breakpoints
53
- - 🔄 **Two-way Binding** - Support for Angular's two-way data binding with `[(value)]`
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
36
+ - 📦 **Standalone Components** - Modern Angular standalone component architecture
37
+ - 🎯 **TypeScript Support** - Full type definitions included
38
+ - ♿ **Accessible** - Built with accessibility best practices
39
+ - 🚀 **Angular 21 Ready** - Built for the latest Angular version
54
40
 
55
41
  ---
56
42
 
@@ -66,13 +52,13 @@ npm install @goat-bravos/intern-hub-layout
66
52
 
67
53
  This library requires the following peer dependencies:
68
54
 
69
- | Package | Version | Required | Description |
70
- | ----------------- | ------- | ----------- | --------------------------------- |
71
- | `@angular/common` | ^21.0.0 | ✅ Yes | Angular common utilities |
72
- | `@angular/core` | ^21.0.0 | ✅ Yes | Angular core framework |
73
- | `@angular/forms` | ^21.0.0 | ✅ Yes | Angular reactive & template forms |
74
- | `@angular/router` | ^21.0.0 | ✅ Yes | Angular routing |
75
- | `dynamic-ds` | ^1.0.3 | ⚠️ Optional | Icon library (if using icons) |
55
+ | Package | Version | Required |
56
+ | ----------------- | ------- | ----------- |
57
+ | `@angular/common` | ^21.0.0 | ✅ Yes |
58
+ | `@angular/core` | ^21.0.0 | ✅ Yes |
59
+ | `@angular/forms` | ^21.0.0 | ✅ Yes |
60
+ | `@angular/router` | ^21.0.0 | ✅ Yes |
61
+ | `dynamic-ds` | ^1.0.2 | ⚠️ Optional |
76
62
 
77
63
  Install peer dependencies if not already present:
78
64
 
@@ -80,12 +66,6 @@ Install peer dependencies if not already present:
80
66
  npm install @angular/common @angular/core @angular/forms @angular/router
81
67
  ```
82
68
 
83
- For icon support, install the optional dependency:
84
-
85
- ```bash
86
- npm install dynamic-ds
87
- ```
88
-
89
69
  ---
90
70
 
91
71
  ## 🚀 Quick Start
@@ -103,15 +83,8 @@ import { HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextC
103
83
  standalone: true,
104
84
  imports: [HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextComponent],
105
85
  templateUrl: "./app.component.html",
106
- styleUrls: ["./app.component.scss"],
107
86
  })
108
- export class AppComponent {
109
- username = "";
110
-
111
- onButtonClick() {
112
- console.log("Button clicked!");
113
- }
114
- }
87
+ export class AppComponent {}
115
88
  ```
116
89
 
117
90
  ### Step 2: Use in Template
@@ -123,77 +96,11 @@ export class AppComponent {
123
96
  <!-- Sidebar -->
124
97
  <app-sidebar [data]="sidebarData"></app-sidebar>
125
98
 
126
- <!-- Main Content Area -->
127
- <div class="content">
128
- <!-- Button -->
129
- <app-button-container content="Click Me" size="md" bgDefault="var(--brand-500)" (buttonClick)="onButtonClick()"> </app-button-container>
130
-
131
- <!-- Input -->
132
- <app-input-text headerInput="Username" placeholder="Enter your username" [required]="true" [(value)]="username"> </app-input-text>
133
- </div>
134
- ```
135
-
136
- ### Step 3: Configure Data Objects (Optional)
137
-
138
- ```typescript
139
- import { HeaderData, SidebarData } from "@goat-bravos/intern-hub-layout";
140
-
141
- export class AppComponent {
142
- headerData: HeaderData = {
143
- headerItems: [
144
- {
145
- icon: "dsi-bell-line",
146
- content: "Notifications",
147
- badge: "5",
148
- method: () => console.log("Notifications clicked"),
149
- },
150
- ],
151
- userName: "John Doe",
152
- logo: "assets/logo.png",
153
- };
154
-
155
- sidebarData: SidebarData = {
156
- backgroundColor: "var(--brand-500)",
157
- menuItems: [
158
- {
159
- iconLeft: "dsi-home-01-line",
160
- content: "Dashboard",
161
- url: "/dashboard",
162
- },
163
- ],
164
- };
165
- }
166
- ```
167
-
168
- ---
99
+ <!-- Button -->
100
+ <app-button-container content="Click Me" size="md" backgroundColor="var(--brand-500)" (buttonClick)="onButtonClick()"></app-button-container>
169
101
 
170
- ## 📁 Project Structure
171
-
172
- ```
173
- intern-hub-layout/
174
- ├── src/
175
- │ ├── libs/
176
- │ │ ├── layouts/ # Layout components
177
- │ │ │ ├── header/ # Header component
178
- │ │ │ └── sidebar/ # Sidebar component
179
- │ │ └── shared/
180
- │ │ └── components/ # Shared UI components
181
- │ │ ├── approval/ # Approval list components
182
- │ │ ├── button/ # Button components
183
- │ │ ├── date-picker/ # Date picker component
184
- │ │ ├── avatar-upload-button/ # Avatar upload button
185
- │ │ ├── file-upload-dropzone/ # Drag & drop file upload
186
- │ │ ├── functional-label/ # Label with icons
187
- │ │ ├── icon/ # Icon component
188
- │ │ ├── input/ # Input components
189
- │ │ ├── modal/ # Modal dialog
190
- │ │ ├── pop-up/ # Confirmation dialogs
191
- │ │ └── table/ # Table components
192
- │ └── public-api.ts # Public API exports
193
- ├── demo/ # Demo application
194
- ├── dist/ # Build output
195
- ├── README.md # This file
196
- └── package.json # Package configuration
102
+ <!-- Input -->
103
+ <app-input-text headerInput="Username" placeholder="Enter your username" [required]="true" [(value)]="username"></app-input-text>
197
104
  ```
198
105
 
199
106
  ---
@@ -234,7 +141,6 @@ export class MyComponent {
234
141
  userIcon: "dsi-user-01-line",
235
142
  dropdownIcon: "dsi-arrow-down-solid",
236
143
  logo: "assets/logo.png",
237
- minWidth: "1200px",
238
144
  };
239
145
  }
240
146
  ```
@@ -252,7 +158,6 @@ interface HeaderData {
252
158
  logo?: string;
253
159
  logoWidth?: string;
254
160
  logoHeight?: string;
255
- minWidth?: string;
256
161
  }
257
162
 
258
163
  interface HeaderAction {
@@ -422,7 +327,7 @@ interface SidebarData {
422
327
 
423
328
  #### ButtonContainerComponent
424
329
 
425
- A highly customizable button component with support for standard icons, custom icon data, multiple size variants, and comprehensive state styling (default, hover, disabled).
330
+ A customizable button with icon support and multiple size variants.
426
331
 
427
332
  **Selector:** `app-button-container`
428
333
 
@@ -433,13 +338,13 @@ import { ButtonContainerComponent, ButtonSize } from "@goat-bravos/intern-hub-la
433
338
  imports: [ButtonContainerComponent],
434
339
  template: `
435
340
  <!-- Basic button -->
436
- <app-button-container content="Submit" size="md" (buttonClick)="onSubmit()"> </app-button-container>
341
+ <app-button-container content="Submit" size="md" (buttonClick)="onSubmit()"></app-button-container>
437
342
 
438
- <!-- Customized button with icons and states -->
439
- <app-button-container content="Download" size="lg" leftIcon="dsi-download-line" bgDefault="#10b981" bgHover="#059669" colorDefault="#ffffff" (buttonClick)="onDownload()"> </app-button-container>
343
+ <!-- Button with icons -->
344
+ <app-button-container content="Download" size="lg" leftIcon="" backgroundColor="#10b981" color="#ffffff" (buttonClick)="onDownload()"></app-button-container>
440
345
 
441
- <!-- Disabled state -->
442
- <app-button-container content="Save" [disabled]="true" bgDisabled="#e5e7eb" colorDisabled="#9ca3af"> </app-button-container>
346
+ <!-- Small button -->
347
+ <app-button-container content="Edit" size="xs" backgroundColor="#f59e0b" (buttonClick)="onEdit()"></app-button-container>
443
348
  `,
444
349
  })
445
350
  export class MyComponent {
@@ -449,38 +354,33 @@ export class MyComponent {
449
354
  onDownload() {
450
355
  console.log("Download initiated");
451
356
  }
357
+ onEdit() {
358
+ console.log("Edit clicked");
359
+ }
452
360
  }
453
361
  ```
454
362
 
455
363
  **Inputs:**
456
364
 
457
- | Input | Type | Default | Description |
458
- | :-------------- | :----------------------------------- | :--------------------------- | :-------------------------------------------------- |
459
- | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| ''` | `'md'` | Button size variant (affects padding/min-size) |
460
- | `content` | `string` | - | Button display text |
461
- | `fontSize` | `string` | - | Custom font size (overrides size variant) |
462
- | `leftIcon` | `string` | - | Icon name for the left side (e.g., 'dsi-plus-line') |
463
- | `leftIconData` | `IconData[]` | - | Complex icon data for the left side |
464
- | `rightIcon` | `string` | - | Icon name for the right side |
465
- | `rightIconData` | `IconData[]` | - | Complex icon data for the right side |
466
- | `bgDefault` | `string` | `'var(--neutral-color-100)'` | Default background color |
467
- | `bgHover` | `string` | `'var(--neutral-color-200)'` | Background color on hover |
468
- | `bgDisabled` | `string` | `'var(--neutral-color-200)'` | Background color when disabled |
469
- | `colorDefault` | `string` | `'var(--neutral-color-900)'` | Default text/icon color |
470
- | `colorHover` | `string` | `'var(--neutral-color-900)'` | Text/icon color on hover |
471
- | `colorDisabled` | `string` | `'var(--neutral-color-500)'` | Text/icon color when disabled |
472
- | `border` | `string` | - | CSS border property (e.g., '1px solid #ccc') |
473
- | `borderRadius` | `string` | `'8px'` | CSS border-radius property |
474
- | `width` | `string` | - | Custom button width |
475
- | `height` | `string` | `'36px'` | Custom button height |
476
- | `padding` | `string` | - | Custom button padding |
477
- | `disabled` | `boolean` | `false` | Whether the button is interactive |
365
+ | Input | Type | Default | Description |
366
+ | ----------------- | ------------------------------ | ---------------------- | --------------------- |
367
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `'md'` (Optional) | Button size variant |
368
+ | `content` | `string` | `''` | Button text |
369
+ | `leftIcon` | `string` | - | Left icon text/class |
370
+ | `rightIcon` | `string` | - | Right icon text/class |
371
+ | `color` | `string` | `'var(--brand-100)'` | Text color |
372
+ | `backgroundColor` | `string` | `'var(--utility-900)'` | Background color |
373
+ | `border` | `string` | - | Border style |
374
+ | `borderRadius` | `string` | - | Button border radius |
375
+ | `width` | `string` | - | Button width |
376
+ | `fontSize` | `string` | - | Custom font size |
377
+ | `buttonData` | `ButtonContainerData` | - | Config object |
478
378
 
479
379
  **Outputs:**
480
380
 
481
- | Output | Type | Description |
482
- | :------------ | :------------------- | :---------------------------------------------- |
483
- | `buttonClick` | `EventEmitter<void>` | Emitted when button is clicked and NOT disabled |
381
+ | Output | Type | Description |
382
+ | ------------- | ------------------- | ------------------------- |
383
+ | `buttonClick` | `EventEmitter<any>` | Emits when button clicked |
484
384
 
485
385
  ---
486
386
 
@@ -648,95 +548,6 @@ export class MyComponent {
648
548
 
649
549
  ---
650
550
 
651
- ### Date Picker Components
652
-
653
- #### DatePickerComponent
654
-
655
- A comprehensive date/range picker with ng-zorro-antd integration supporting single selection, range selection, and multiple modes.
656
-
657
- **Selector:** `app-date-picker`
658
-
659
- ```typescript
660
- import { DatePickerComponent } from "@goat-bravos/intern-hub-layout";
661
-
662
- @Component({
663
- imports: [DatePickerComponent],
664
- template: `
665
- <!-- Single date picker -->
666
- <app-date-picker headerInput="Start Date" mode="date" [(value)]="selectedDate" (dateChange)="onDateChange($event)"></app-date-picker>
667
-
668
- <!-- Date range picker -->
669
- <app-date-picker headerInput="Date Range" mode="default" isRange="true" [(value)]="dateRange" (rangeChange)="onRangeChange($event)"></app-date-picker>
670
-
671
- <!-- Week picker -->
672
- <app-date-picker headerInput="Select Week" mode="week" [(value)]="weekDate"></app-date-picker>
673
-
674
- <!-- Month picker -->
675
- <app-date-picker headerInput="Select Month" mode="month" [(value)]="monthDate"></app-date-picker>
676
-
677
- <!-- Date and Time picker -->
678
- <app-date-picker headerInput="Date & Time" mode="date" showTime="true" [(value)]="dateTime"></app-date-picker>
679
- `,
680
- })
681
- export class MyComponent {
682
- selectedDate: Date | null = null;
683
- dateRange: [Date, Date] | null = null;
684
- weekDate: Date | null = null;
685
- monthDate: Date | null = null;
686
- dateTime: Date | null = null;
687
-
688
- onDateChange(date: Date) {
689
- console.log("Date selected:", date);
690
- }
691
-
692
- onRangeChange(range: [Date, Date]) {
693
- console.log("Date range selected:", range);
694
- }
695
- }
696
- ```
697
-
698
- **Inputs:**
699
-
700
- | Input | Type | Default | Description |
701
- | ------------------- | ---------------------------------------------------------- | --------------- | ---------------------------------- |
702
- | `headerInput` | `string` | `''` | Label text above picker |
703
- | `value` | `Date \| [Date, Date] \| null` | `null` | Selected date(s) value |
704
- | `mode` | `'date' \| 'week' \| 'month' \| 'quarter' \| 'year'` | `'date'` | Picker mode |
705
- | `isRange` | `boolean` | `false` | Enable range selection |
706
- | `showTime` | `boolean` | `false` | Show time selection |
707
- | `placeholder` | `string` | `'Select date'` | Placeholder text |
708
- | `format` | `string` | `'dd/MM/yyyy'` | Date format string |
709
- | `required` | `boolean` | `false` | Show required indicator |
710
- | `readonly` | `boolean` | `false` | Read-only state |
711
- | `disabled` | `boolean` | `false` | Disabled state |
712
- | `disabledDate` | `(date: Date) => boolean` | - | Function to disable specific dates |
713
- | `dropdownPlacement` | `'topLeft' \| 'topRight' \| 'bottomLeft' \| 'bottomRight'` | `'bottomLeft'` | Dropdown position |
714
- | `width` | `string` | `'100%'` | Component width |
715
-
716
- **Outputs:**
717
-
718
- | Output | Type | Description |
719
- | ------------- | ------------------------------------ | ---------------------------------- |
720
- | `dateChange` | `EventEmitter<Date \| null>` | Emits when single date is selected |
721
- | `rangeChange` | `EventEmitter<[Date, Date] \| null>` | Emits when date range is selected |
722
- | `openChange` | `EventEmitter<boolean>` | Emits when picker opens/closes |
723
- | `ok` | `EventEmitter<Date \| [Date, Date]>` | Emits when OK button is clicked |
724
- | `panelChange` | `EventEmitter<any>` | Emits on panel change events |
725
-
726
- **Features:**
727
-
728
- - ✅ **Multiple Modes** - Date, week, month, quarter, year selection
729
- - ✅ **Range Selection** - Pick date ranges for date range inputs
730
- - ✅ **Time Support** - Include time selection with dates
731
- - ✅ **Date Disabling** - Disable specific dates via custom function
732
- - ✅ **Customizable Format** - Change date format string
733
- - ✅ **Dropdown Control** - Position popup relative to input
734
- - ✅ **Form Integration** - ControlValueAccessor for form support
735
-
736
- ---
737
-
738
- ### Table Components
739
-
740
551
  #### InputCalendarComponent
741
552
 
742
553
  A date picker with auto-formatting (dd/mm/yyyy) and validation.
@@ -791,6 +602,8 @@ export class MyComponent {
791
602
 
792
603
  ---
793
604
 
605
+ ### Table Components
606
+
794
607
  #### TableHeaderComponent & TableBodyComponent
795
608
 
796
609
  Table components with customizable columns and template support.
@@ -936,128 +749,11 @@ interface ApprovalListItemInterface {
936
749
 
937
750
  ---
938
751
 
939
- ---
940
-
941
- #### ApprovalListItemComponent
942
-
943
- A single item component for the approval list, can be used independently.
944
-
945
- **Selector:** `app-approval-list-item`
946
-
947
- ```typescript
948
- import { ApprovalListItemComponent } from "@goat-bravos/intern-hub-layout";
949
-
950
- @Component({
951
- imports: [ApprovalListItemComponent],
952
- template: ` <app-approval-list-item name="John Doe - Request #123" [date]="requestDate"></app-approval-list-item> `,
953
- })
954
- export class MyComponent {
955
- requestDate = new Date();
956
- }
957
- ```
958
-
959
- **Inputs:**
960
-
961
- | Input | Type | Description |
962
- | --------------- | ------------------ | ------------------------------ |
963
- | `name` | `string` | Main text/name to display |
964
- | `date` | `Date` | Date object to display |
965
- | `rightTemplate` | `TemplateRef<any>` | Custom template for right side |
966
- | `rightContext` | `any` | Context for the right template |
967
-
968
- ---
969
-
970
- ### Modal Components
971
-
972
- #### ModalComponent
973
-
974
- A flexible modal dialog with customizable themes and responsive design, supporting named content slots for body and footer.
975
-
976
- **Selector:** `app-modal`
977
-
978
- ```typescript
979
- import { ModalComponent } from "@goat-bravos/intern-hub-layout";
980
- import { CommonModule } from "@angular/common";
981
-
982
- @Component({
983
- imports: [CommonModule, ModalComponent],
984
- template: `
985
- <!-- Trigger button -->
986
- <button (click)="isModalOpen = true">Open Modal</button>
987
-
988
- <!-- Modal component -->
989
- <app-modal [title]="'User Settings'" [isOpen]="isModalOpen" [width]="'600px'" [minHeight]="'400px'" [theme]="'default'" (closeModal)="isModalOpen = false">
990
- <!-- Modal Body Content -->
991
- <div modal-body>
992
- <h3>Account Information</h3>
993
- <p>Update your account details and preferences below.</p>
994
- <!-- Your form or other components -->
995
- </div>
996
-
997
- <!-- Modal Footer Content -->
998
- <div modal-footer>
999
- <button (click)="isModalOpen = false">Cancel</button>
1000
- <button class="primary" (click)="saveSettings()">Save Changes</button>
1001
- </div>
1002
- </app-modal>
1003
- `,
1004
- })
1005
- export class MyComponent {
1006
- isModalOpen = false;
1007
-
1008
- saveSettings() {
1009
- console.log("Settings saved");
1010
- this.isModalOpen = false;
1011
- }
1012
- }
1013
- ```
1014
-
1015
- **Inputs:**
1016
-
1017
- | Input | Type | Default | Description |
1018
- | ----------- | ---------------------- | ----------- | ------------------------- |
1019
- | `title` | `string` | `''` | Modal title text |
1020
- | `width` | `string` | `'800px'` | Modal width (CSS value) |
1021
- | `minHeight` | `string` | `'300px'` | Minimum modal height |
1022
- | `isOpen` | `boolean` | `false` | Controls modal visibility |
1023
- | `theme` | `'default' \| 'white'` | `'default'` | Visual color theme |
1024
-
1025
- **Outputs:**
1026
-
1027
- | Output | Type | Description |
1028
- | ------------ | -------------------- | --------------------------------- |
1029
- | `closeModal` | `EventEmitter<void>` | Emits when modal should be closed |
1030
-
1031
- **Content Projection (Slots):**
1032
-
1033
- The modal uses named content projection to organize your content:
1034
-
1035
- - `[modal-body]`: The main content area of the modal.
1036
- - `[modal-footer]`: The bottom action area (typically for buttons).
1037
-
1038
- ```html
1039
- <app-modal [title]="'Custom Modal'" [isOpen]="true">
1040
- <div modal-body>
1041
- <!-- Main content goes here -->
1042
- </div>
1043
- <div modal-footer>
1044
- <!-- Footer actions go here -->
1045
- </div>
1046
- </app-modal>
1047
- ```
1048
-
1049
- **Themes:**
1050
-
1051
- - `default` - Uses `var(--brand-100)` background with `var(--brand-600)` title.
1052
- - `white` - Uses `var(--neutral-color-10)` background with `var(--neutral-color-50)` title.
1053
-
1054
- ---
1055
-
1056
752
  ### Pop-up Components
1057
753
 
1058
754
  #### PopUpConfirmComponent
1059
755
 
1060
- An accessible confirmation modal dialog for user confirmations.
756
+ An accessible confirmation modal dialog.
1061
757
 
1062
758
  **Selector:** `app-pop-up-confirm`
1063
759
 
@@ -1109,134 +805,6 @@ export class MyComponent {
1109
805
 
1110
806
  ---
1111
807
 
1112
- ### Upload Components
1113
-
1114
- ---
1115
-
1116
- #### AvatarUploadButtonComponent
1117
-
1118
- A dedicated button for uploading avatar images with preview functionality.
1119
-
1120
- **Selector:** `app-avatar-upload-button`
1121
-
1122
- ```typescript
1123
- import { AvatarUploadButtonComponent, AvatarUploadedFile } from "@goat-bravos/intern-hub-layout";
1124
-
1125
- @Component({
1126
- imports: [AvatarUploadButtonComponent],
1127
- template: ` <app-avatar-upload-button [label]="'Avatar'" [required]="true" [buttonText]="'Upload Avatar'" (fileChange)="onAvatarChange($event)"></app-avatar-upload-button> `,
1128
- })
1129
- export class MyComponent {
1130
- onAvatarChange(file: AvatarUploadedFile | null) {
1131
- if (file) {
1132
- console.log("Avatar uploaded:", file.fileName, file.previewUrl);
1133
- } else {
1134
- console.log("Avatar removed");
1135
- }
1136
- }
1137
- }
1138
- ```
1139
-
1140
- **Inputs:**
1141
-
1142
- | Input | Type | Default | Description |
1143
- | --------------- | --------- | ------------------------------- | ------------------ |
1144
- | `label` | `string` | `''` | Label text |
1145
- | `required` | `boolean` | `false` | Required indicator |
1146
- | `showTooltip` | `boolean` | `false` | Show info tooltip |
1147
- | `tooltipText` | `string` | `''` | Tooltip content |
1148
- | `buttonText` | `string` | `'Tải file lên'` | Button text |
1149
- | `acceptFormats` | `string` | `'.png,.jpeg,.jpg'` | Accepted formats |
1150
- | `helperText` | `string` | `'Định dạng .png, .jpeg, .jpg'` | Helper text below |
1151
-
1152
- **Outputs:**
1153
-
1154
- | Output | Type | Description |
1155
- | ------------ | -------------------------------- | ----------- | -------------------------------- |
1156
- | `fileChange` | `EventEmitter<AvatarUploadedFile | null>` | Emits uploaded file data or null |
1157
-
1158
- **Interfaces:**
1159
-
1160
- ```typescript
1161
- interface AvatarUploadedFile {
1162
- id: string;
1163
- file: File;
1164
- fileName: string;
1165
- previewUrl: string | null;
1166
- }
1167
- ```
1168
-
1169
- ---
1170
-
1171
- #### FileUploadDropzoneComponent
1172
-
1173
- A drag-and-drop file upload zone with multiple file support.
1174
-
1175
- **Selector:** `app-file-upload-dropzone`
1176
-
1177
- ```typescript
1178
- import { FileUploadDropzoneComponent } from "@goat-bravos/intern-hub-layout";
1179
-
1180
- @Component({
1181
- imports: [FileUploadDropzoneComponent],
1182
- template: `
1183
- <!-- Single file upload -->
1184
- <app-file-upload-dropzone [label]="'Upload Assignment'" [buttonText]="'Browse Files'" [maxSize]="'5MB'" [acceptFormats]="'.pdf,.doc,.docx'" (fileSelected)="onSingleFileSelected($event)"></app-file-upload-dropzone>
1185
-
1186
- <!-- Multiple files upload -->
1187
- <app-file-upload-dropzone [label]="'Upload Documents'" [buttonText]="'Select Multiple Files'" [maxSize]="'10MB'" [acceptFormats]="'.docx,.xlsx,.png,.jpg,.jpeg,.pdf'" [helperText]="'You can drag and drop multiple files here'" (filesSelected)="onMultipleFilesSelected($event)"></app-file-upload-dropzone>
1188
- `,
1189
- })
1190
- export class MyComponent {
1191
- onSingleFileSelected(file: File) {
1192
- console.log("Single file selected:", file.name);
1193
- // Handle single file upload
1194
- }
1195
-
1196
- onMultipleFilesSelected(files: File[]) {
1197
- console.log(`${files.length} files selected`);
1198
- files.forEach((file) => {
1199
- console.log("File:", file.name, file.size);
1200
- });
1201
- // Handle multiple files upload
1202
- }
1203
- }
1204
- ```
1205
-
1206
- **Inputs:**
1207
-
1208
- | Input | Type | Default | Description |
1209
- | --------------- | -------- | --------------------------------------- | ---------------------------- |
1210
- | `label` | `string` | `'Thêm file bài học'` | Label text above dropzone |
1211
- | `buttonText` | `string` | `'Tải lên'` | Button text |
1212
- | `maxSize` | `string` | `'10MB'` | Maximum file size |
1213
- | `acceptFormats` | `string` | `'.docx,.xlsx,.png,.jpg,.jpeg,.pdf'` | Accepted file formats |
1214
- | `helperText` | `string` | Auto-generated from maxSize and formats | Helper text (auto or custom) |
1215
-
1216
- **Outputs:**
1217
-
1218
- | Output | Type | Description |
1219
- | --------------- | ---------------------- | -------------------------------------- |
1220
- | `fileSelected` | `EventEmitter<File>` | Emits when single file is selected |
1221
- | `filesSelected` | `EventEmitter<File[]>` | Emits when multiple files are selected |
1222
-
1223
- **Features:**
1224
-
1225
- - ✅ **Drag & Drop Support** - Users can drag files directly onto the dropzone
1226
- - ✅ **Visual Feedback** - Highlighted border when dragging files over the zone
1227
- - ✅ **Multiple Files** - Supports both single and multiple file selection
1228
- - ✅ **Format Validation** - Restricts file types based on `acceptFormats`
1229
- - ✅ **Size Display** - Shows maximum allowed file size
1230
- - ✅ **Accessible** - Keyboard-accessible file input
1231
-
1232
- **Usage Tips:**
1233
-
1234
- - The component will emit `fileSelected` for single file uploads
1235
- - The component will emit `filesSelected` for multiple file uploads
1236
- - Helper text is automatically generated from `maxSize` and `acceptFormats`, but can be overridden
1237
-
1238
- ---
1239
-
1240
808
  ### Icon Components
1241
809
 
1242
810
  #### IconComponent
@@ -1335,572 +903,34 @@ export class MyComponent {
1335
903
 
1336
904
  ---
1337
905
 
1338
- ## 💡 Best Practices
1339
-
1340
- ### Component Usage
1341
-
1342
- #### 1. **Use Two-Way Binding for Forms**
1343
-
1344
- ```typescript
1345
- // ✅ Good - Two-way binding
1346
- <app-input-text
1347
- headerInput="Email"
1348
- [(value)]="userEmail"
1349
- ></app-input-text>
1350
-
1351
- // ❌ Avoid - One-way binding without handling value changes
1352
- <app-input-text
1353
- headerInput="Email"
1354
- [value]="userEmail"
1355
- ></app-input-text>
1356
- ```
1357
-
1358
- #### 2. **Leverage CSS Custom Properties for Theming**
1359
-
1360
- ```typescript
1361
- // Define your theme colors in global CSS
1362
- :root {
1363
- --brand-500: #3b82f6;
1364
- --brand-600: #2563eb;
1365
- --neutral-100: #f5f5f5;
1366
- }
1367
-
1368
- // Use them in components
1369
- <app-button-container
1370
- content="Submit"
1371
- bgDefault="var(--brand-500)"
1372
- colorDefault="var(--neutral-100)"
1373
- ></app-button-container>
1374
- ```
1375
-
1376
- #### 3. **Import Only What You Need**
1377
-
1378
- ```typescript
1379
- // ✅ Good - Import only required components
1380
- import { ButtonContainerComponent, InputTextComponent } from "@goat-bravos/intern-hub-layout";
1381
-
1382
- // ❌ Avoid - Wildcard imports
1383
- import * from "@goat-bravos/intern-hub-layout";
1384
- ```
1385
-
1386
- #### 4. **Use Interfaces for Type Safety**
1387
-
1388
- ```typescript
1389
- import { HeaderData, SidebarData } from "@goat-bravos/intern-hub-layout";
1390
-
1391
- export class MyComponent {
1392
- // ✅ Good - Typed data objects
1393
- headerData: HeaderData = {
1394
- headerItems: [],
1395
- userName: "John Doe",
1396
- };
1397
-
1398
- // ❌ Avoid - Untyped objects
1399
- headerData: any = {
1400
- headerItems: [],
1401
- userName: "John Doe",
1402
- };
1403
- }
1404
- ```
1405
-
1406
- #### 5. **Handle Events Properly**
1407
-
1408
- ```typescript
1409
- // ✅ Good - Proper event handling
1410
- <app-button-container
1411
- content="Delete"
1412
- (buttonClick)="confirmDelete()"
1413
- ></app-button-container>
1414
-
1415
- confirmDelete() {
1416
- if (confirm("Are you sure?")) {
1417
- this.deleteItem();
1418
- }
1419
- }
1420
-
1421
- // ❌ Avoid - Inline complex logic
1422
- <app-button-container
1423
- content="Delete"
1424
- (buttonClick)="confirm('Are you sure?') && deleteItem()"
1425
- ></app-button-container>
1426
- ```
1427
-
1428
- ### Performance
1429
-
1430
- - **Use `OnPush` Change Detection**: All library components use `OnPush` for optimal performance
1431
- - **Avoid Frequent Re-renders**: Pass stable object references to avoid unnecessary re-renders
1432
- - **Lazy Load Large Components**: Use dynamic imports for modals and heavy components
1433
-
1434
- ### Accessibility
1435
-
1436
- - **Always Provide Labels**: Use `headerInput` or `label` properties for form elements
1437
- - **Use Semantic Buttons**: The library components handle semantic HTML automatically
1438
- - **Test Keyboard Navigation**: Ensure all interactive components are keyboard accessible
1439
- - **Provide Alt Text**: When using images in headers or icons, provide descriptive text
1440
-
1441
- ---
1442
-
1443
- ## 🔧 Troubleshooting
1444
-
1445
- ### Common Issues
1446
-
1447
- #### Issue: Components not displaying correctly
1448
-
1449
- **Possible Causes:**
1450
-
1451
- - Missing peer dependencies
1452
- - CSS conflicts with existing styles
1453
- - Incorrect selector usage
1454
-
1455
- **Solutions:**
1456
-
1457
- ```bash
1458
- # Verify all peer dependencies are installed
1459
- npm list @angular/core @angular/common @angular/forms @angular/router
1460
-
1461
- # Check package.json for correct versions
1462
- npm install @angular/common@^21.0.0 @angular/core@^21.0.0
1463
- ```
1464
-
1465
- #### Issue: Icons not showing
1466
-
1467
- **Possible Causes:**
1468
-
1469
- - `dynamic-ds` library not installed
1470
- - Icon class names incorrect
1471
-
1472
- **Solutions:**
1473
-
1474
- ```bash
1475
- # Install the optional icon library
1476
- npm install dynamic-ds
1477
-
1478
- # Verify icon names (they should start with 'dsi-')
1479
- <app-icon icon="dsi-home-01-line"></app-icon>
1480
- ```
1481
-
1482
- #### Issue: Two-way binding not working
1483
-
1484
- **Possible Causes:**
1485
-
1486
- - Missing `FormsModule` import
1487
- - Incorrect syntax (`[(value)]` vs `[value]`)
1488
-
1489
- **Solutions:**
1490
-
1491
- ```typescript
1492
- // Ensure FormsModule is imported
1493
- import { FormsModule } from '@angular/forms';
1494
-
1495
- @Component({
1496
- imports: [FormsModule, InputTextComponent],
1497
- // ...
1498
- })
1499
-
1500
- // Use correct two-way binding syntax
1501
- <app-input-text [(value)]="myValue"></app-input-text>
1502
- ```
1503
-
1504
- #### Issue: TypeScript errors about missing interfaces
1505
-
1506
- **Solutions:**
1507
-
1508
- ```typescript
1509
- // Import the required interfaces
1510
- import { HeaderData, SidebarData, ButtonContainerData, IconData } from "@goat-bravos/intern-hub-layout";
1511
- ```
1512
-
1513
- #### Issue: Sidebar not collapsing/expanding
1514
-
1515
- **Possible Causes:**
1516
-
1517
- - Missing router outlet
1518
- - Incorrect configuration
1519
-
1520
- **Solutions:**
1521
-
1522
- ```typescript
1523
- // Ensure Angular Router is properly configured
1524
- import { RouterOutlet } from '@angular/router';
1525
-
1526
- @Component({
1527
- imports: [RouterOutlet, SidebarComponent],
1528
- template: `
1529
- <app-sidebar [data]="sidebarData"></app-sidebar>
1530
- <router-outlet></router-outlet>
1531
- `
1532
- })
1533
- ```
1534
-
1535
- ### Getting Help
1536
-
1537
- If you encounter issues not covered here:
1538
-
1539
- 1. **Check the Demo App**: Review the `/demo` directory for working examples
1540
- 2. **GitHub Issues**: Search for [existing issues](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
1541
- 3. **Create an Issue**: Provide a minimal reproduction example
1542
- 4. **Stack Overflow**: Tag with `angular` and `intern-hub-layout`
1543
-
1544
- ---
1545
-
1546
- ## 📝 Changelog
1547
-
1548
- ### Version 3.0.15 (Current)
1549
-
1550
- **Added:**
1551
-
1552
- - ✨ DatePickerComponent with ng-zorro-antd integration
1553
- - Support for single date, range, and multiple modes (date, week, month, quarter, year)
1554
- - Time selection support
1555
- - Date disabling functionality
1556
- - Customizable date formatting
1557
- - ✨ Modal component with theme support
1558
- - ✨ File upload components (AvatarUploadButtonComponent and FileUploadDropzoneComponent)
1559
- - ✨ Drag-and-drop file upload functionality
1560
- - ✨ Enhanced accessibility features
1561
-
1562
- **Improved:**
1563
-
1564
- - 🔧 Better TypeScript type definitions
1565
- - 🔧 Optimized component performance with OnPush
1566
- - 📚 Comprehensive README documentation with DatePicker examples
1567
- - 🔧 Updated project structure documentation
1568
-
1569
- **Fixed:**
1570
-
1571
- - 🐛 Icon color inheritance issues
1572
- - 🐛 Sidebar collapse/expand animations
1573
- - 🐛 Input validation edge cases
1574
-
1575
- ### Version 3.0.x
1576
-
1577
- **Added:**
1578
-
1579
- - Support for Angular 21
1580
- - Standalone component architecture
1581
- - Input components (text, stepper, calendar)
1582
- - Table components with custom templates
1583
- - Approval list components
1584
-
1585
- **Changed:**
1586
-
1587
- - Migrated from NgModules to standalone components
1588
- - Updated to TypeScript 5.9
1589
- - Improved CSS architecture
1590
-
1591
- ### Version 2.0.x
1592
-
1593
- **Added:**
1594
-
1595
- - Header and sidebar layout components
1596
- - Button components
1597
- - Icon support with dynamic-ds
1598
-
1599
- ---
1600
-
1601
906
  ## 🛠️ Development
1602
907
 
1603
- ### Prerequisites
1604
-
1605
- - Node.js (v18 or higher)
1606
- - npm (v9 or higher)
1607
- - Angular CLI (v21 or higher)
1608
-
1609
908
  ### Building the library
1610
909
 
1611
- Build the library for production:
1612
-
1613
910
  ```bash
1614
911
  npm run build
1615
912
  ```
1616
913
 
1617
- This will compile the library to the `dist/intern-hub-layout` directory.
1618
-
1619
914
  ### Running the demo app
1620
915
 
1621
- Start the demo application to see all components in action:
1622
-
1623
916
  ```bash
1624
917
  npm run demo
1625
918
  ```
1626
919
 
1627
- Navigate to `http://localhost:4200/` to view the demo.
1628
-
1629
- ### Development Workflow
1630
-
1631
- 1. **Make changes** to components in `src/libs/`
1632
- 2. **Build the library** with `npm run build`
1633
- 3. **Test in demo** app with `npm run demo`
1634
- 4. **Verify build** with `npm run build` after changes
1635
-
1636
- ### Publishing to npm
1637
-
1638
- #### Dry Run (Test Before Publishing)
1639
-
1640
- ```bash
1641
- npm run publish:lib:dry
1642
- ```
1643
-
1644
- This will show what will be published without actually publishing.
1645
-
1646
- #### Publish to npm Registry
1647
-
1648
- ```bash
1649
- npm run publish:lib
1650
- ```
1651
-
1652
- This will:
1653
-
1654
- 1. Build the library
1655
- 2. Navigate to the dist directory
1656
- 3. Publish to npm
1657
-
1658
- #### Create a Package Tarball
1659
-
1660
- ```bash
1661
- npm run pack:lib
1662
- ```
1663
-
1664
- This will:
1665
-
1666
- 1. Increment the patch version
1667
- 2. Build the library
1668
- 3. Create a `.tgz` file for local testing
1669
-
1670
- ### Testing Locally
1671
-
1672
- To test the library in another Angular project before publishing:
1673
-
1674
- ```bash
1675
- # In the library project
1676
- npm run pack:lib
1677
-
1678
- # In your test project
1679
- npm install /path/to/intern-hub-layout/dist/intern-hub-layout/goat-bravos-intern-hub-layout-3.0.15.tgz
1680
- ```
1681
-
1682
- ### Project Scripts
1683
-
1684
- | Script | Description |
1685
- | ------------------------- | -------------------------------- |
1686
- | `npm run build` | Build the library for production |
1687
- | `npm run demo` | Start the demo application |
1688
- | `npm run publish:lib` | Build and publish to npm |
1689
- | `npm run publish:lib:dry` | Test publish without uploading |
1690
- | `npm run pack:lib` | Create a local package tarball |
1691
-
1692
920
  ---
1693
921
 
1694
922
  ## 🤝 Contributing
1695
923
 
1696
- We welcome contributions from the community! Here's how you can help:
1697
-
1698
- ### Getting Started
1699
-
1700
- 1. **Fork the repository**
1701
-
1702
- ```bash
1703
- git clone https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout.git
1704
- ```
1705
-
1706
- 2. **Create a feature branch**
1707
-
1708
- ```bash
1709
- git checkout -b feature/AmazingFeature
1710
- ```
1711
-
1712
- 3. **Make your changes**
1713
- - Follow the existing code style
1714
- - Add tests if applicable
1715
- - Update documentation
1716
-
1717
- 4. **Commit your changes**
1718
-
1719
- ```bash
1720
- git commit -m 'feat: Add some AmazingFeature'
1721
- ```
1722
-
1723
- We follow [Conventional Commits](https://www.conventionalcommits.org/):
1724
- - `feat:` - New feature
1725
- - `fix:` - Bug fix
1726
- - `docs:` - Documentation changes
1727
- - `style:` - Code style changes (formatting, etc.)
1728
- - `refactor:` - Code refactoring
1729
- - `test:` - Adding tests
1730
- - `chore:` - Maintenance tasks
1731
-
1732
- 5. **Push to your fork**
1733
-
1734
- ```bash
1735
- git push origin feature/AmazingFeature
1736
- ```
1737
-
1738
- 6. **Open a Pull Request**
1739
-
1740
- Go to the [repository](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout) and create a pull request.
1741
-
1742
- ### Contribution Guidelines
1743
-
1744
- #### Code Style
924
+ Contributions are welcome! Please feel free to submit a Pull Request.
1745
925
 
1746
- - Use TypeScript strict mode
1747
- - Follow Angular style guide
1748
- - Use meaningful variable and function names
1749
- - Add comments for complex logic
1750
- - Keep components focused and single-purpose
1751
-
1752
- #### Component Guidelines
1753
-
1754
- When creating a new component:
1755
-
1756
- 1. **Create in appropriate directory**
1757
-
1758
- ```
1759
- src/libs/shared/components/your-component/
1760
- ├── your-component.component.ts
1761
- ├── your-component.component.html
1762
- ├── your-component.component.scss
1763
- └── your-component.model.ts (if needed)
1764
- ```
1765
-
1766
- 2. **Use standalone components**
1767
-
1768
- ```typescript
1769
- @Component({
1770
- selector: 'app-your-component',
1771
- standalone: true,
1772
- imports: [CommonModule],
1773
- // ...
1774
- })
1775
- ```
1776
-
1777
- 3. **Export in public-api.ts**
1778
-
1779
- ```typescript
1780
- export * from "./libs/shared/components/your-component/your-component.component";
1781
- ```
1782
-
1783
- 4. **Document in README.md**
1784
- - Add usage examples
1785
- - Document all inputs and outputs
1786
- - Include practical examples
1787
-
1788
- #### Testing
1789
-
1790
- Before submitting a PR:
1791
-
1792
- - [ ] Build the library successfully (`npm run build`)
1793
- - [ ] Test in demo app (`npm run demo`)
1794
- - [ ] Verify no console errors or warnings
1795
- - [ ] Test in different browsers (Chrome, Firefox, Safari)
1796
- - [ ] Check accessibility (keyboard navigation, screen readers)
1797
-
1798
- #### Pull Request Process
1799
-
1800
- 1. Update the README.md with details of changes
1801
- 2. Update version numbers following [SemVer](https://semver.org/)
1802
- 3. Ensure the PR description clearly describes the problem and solution
1803
- 4. Link any related issues
1804
-
1805
- ### Questions or Issues?
1806
-
1807
- - Open an [issue](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
1808
- - Reach out to the maintainers
1809
- - Check existing issues and PRs first
926
+ 1. Fork the project
927
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
928
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
929
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
930
+ 5. Open a Pull Request
1810
931
 
1811
932
  ---
1812
933
 
1813
934
  ## 📄 License
1814
935
 
1815
- This project is licensed under the **MIT License**.
1816
-
1817
- ### MIT License
1818
-
1819
- ```
1820
- Copyright (c) 2024 FPT IS Intern Team
1821
-
1822
- Permission is hereby granted, free of charge, to any person obtaining a copy
1823
- of this software and associated documentation files (the "Software"), to deal
1824
- in the Software without restriction, including without limitation the rights
1825
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1826
- copies of the Software, and to permit persons to whom the Software is
1827
- furnished to do so, subject to the following conditions:
1828
-
1829
- The above copyright notice and this permission notice shall be included in all
1830
- copies or substantial portions of the Software.
1831
-
1832
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1833
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1834
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1835
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1836
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1837
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1838
- SOFTWARE.
1839
- ```
1840
-
1841
- ---
1842
-
1843
- ## 🔗 Links & Resources
1844
-
1845
- ### Official Links
1846
-
1847
- - **📦 npm Package**: [@goat-bravos/intern-hub-layout](https://www.npmjs.com/package/@goat-bravos/intern-hub-layout)
1848
- - **💻 GitHub Repository**: [FPT-IS-Intern/Intern-Hub-FE-Layout](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout)
1849
- - **📝 Changelog**: [GitHub Releases](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/releases)
1850
- - **🐛 Bug Reports**: [GitHub Issues](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
1851
-
1852
- ### Related Projects
1853
-
1854
- - **Angular**: [https://angular.dev](https://angular.dev)
1855
- - **TypeScript**: [https://www.typescriptlang.org](https://www.typescriptlang.org)
1856
- - **Dynamic DS**: Icon library used by this project
1857
-
1858
- ### External Resources
1859
-
1860
- - [Angular Style Guide](https://angular.dev/style-guide)
1861
- - [TypeScript Documentation](https://www.typescriptlang.org/docs/)
1862
- - [Web Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG21/quickref/)
1863
- - [Conventional Commits](https://www.conventionalcommits.org/)
1864
- - [Semantic Versioning](https://semver.org/)
1865
-
1866
- ---
1867
-
1868
- ## 💬 Support
1869
-
1870
- ### Need Help?
1871
-
1872
- - 💡 **General Questions**: Check the [Troubleshooting](#-troubleshooting) section
1873
- - 📖 **Documentation**: Read through component examples above
1874
- - 🐛 **Bug Reports**: [Create an issue](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues/new)
1875
- - ✨ **Feature Requests**: [Suggest a feature](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues/new)
1876
- - 💬 **Discussions**: [GitHub Discussions](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/discussions)
1877
-
1878
- ### Stay Updated
1879
-
1880
- - ⭐ Star the repository to stay updated
1881
- - 👁️ Watch for new releases
1882
- - 🍴 Fork to contribute
1883
-
1884
- ---
1885
-
1886
- ## 🙏 Acknowledgments
1887
-
1888
- Built with ❤️ by the **FPT IS Intern Team**
1889
-
1890
- Special thanks to:
1891
-
1892
- - The Angular team for an amazing framework
1893
- - All contributors who help improve this library
1894
- - The open-source community
1895
-
1896
- ---
1897
-
1898
- <div align="center">
1899
-
1900
- **[⬆ Back to Top](#-intern-hub-layout)**
1901
-
1902
- Made with 💙 by [FPT IS Intern Team](https://github.com/FPT-IS-Intern)
1903
-
1904
- **📦 @goat-bravos/intern-hub-layout** | **v3.0.15** | **MIT License**
1905
-
1906
- </div>
936
+ This project is licensed under the MIT License - see the LICENSE file for details.