@goat-bravos/intern-hub-layout 3.0.4 → 3.0.7
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,8 +4,9 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|

|
|
7
|
+

|
|
7
8
|
|
|
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.
|
|
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.
|
|
9
10
|
|
|
10
11
|
---
|
|
11
12
|
|
|
@@ -14,29 +15,38 @@ A comprehensive Angular library providing reusable layout components and shared
|
|
|
14
15
|
- [Features](#-features)
|
|
15
16
|
- [Installation](#-installation)
|
|
16
17
|
- [Quick Start](#-quick-start)
|
|
18
|
+
- [Project Structure](#-project-structure)
|
|
17
19
|
- [Components](#-components)
|
|
18
20
|
- [Layout Components](#layout-components)
|
|
19
21
|
- [Button Components](#button-components)
|
|
20
22
|
- [Input Components](#input-components)
|
|
21
23
|
- [Table Components](#table-components)
|
|
22
24
|
- [Approval Components](#approval-components)
|
|
25
|
+
- [Modal Components](#modal-components)
|
|
23
26
|
- [Pop-up Components](#pop-up-components)
|
|
27
|
+
- [Upload Components](#upload-components)
|
|
24
28
|
- [Icon Components](#icon-components)
|
|
25
|
-
- [
|
|
29
|
+
- [Best Practices](#-best-practices)
|
|
30
|
+
- [Troubleshooting](#-troubleshooting)
|
|
31
|
+
- [Development](#️-development)
|
|
26
32
|
- [Contributing](#-contributing)
|
|
33
|
+
- [Changelog](#-changelog)
|
|
27
34
|
- [License](#-license)
|
|
28
35
|
|
|
29
36
|
---
|
|
30
37
|
|
|
31
38
|
## ✨ Features
|
|
32
39
|
|
|
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
|
|
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
|
|
40
|
+
- 🎨 **Pre-built Layouts** - Header and sidebar components with smooth hover effects and animations
|
|
41
|
+
- 🧩 **Reusable UI Components** - Buttons, inputs, tables, modals, file uploads, approval lists, and more
|
|
42
|
+
- 🔧 **Highly Configurable** - Extensive customization via input properties and CSS custom properties
|
|
43
|
+
- 📦 **Standalone Components** - Modern Angular standalone component architecture (no NgModules required)
|
|
44
|
+
- 🎯 **TypeScript Support** - Full type definitions and interfaces included
|
|
45
|
+
- ♿ **Accessible** - Built with accessibility best practices (ARIA attributes, keyboard navigation)
|
|
46
|
+
- 🚀 **Angular 21 Ready** - Built for the latest Angular version with Signal support
|
|
47
|
+
- 🎭 **Theme Support** - Customizable color schemes using CSS variables
|
|
48
|
+
- 📱 **Responsive** - Mobile-first design with responsive breakpoints
|
|
49
|
+
- 🔄 **Two-way Binding** - Support for Angular's two-way data binding with `[(value)]`
|
|
40
50
|
|
|
41
51
|
---
|
|
42
52
|
|
|
@@ -52,13 +62,13 @@ npm install @goat-bravos/intern-hub-layout
|
|
|
52
62
|
|
|
53
63
|
This library requires the following peer dependencies:
|
|
54
64
|
|
|
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.
|
|
65
|
+
| Package | Version | Required | Description |
|
|
66
|
+
| ----------------- | ------- | ----------- | --------------------------------- |
|
|
67
|
+
| `@angular/common` | ^21.0.0 | ✅ Yes | Angular common utilities |
|
|
68
|
+
| `@angular/core` | ^21.0.0 | ✅ Yes | Angular core framework |
|
|
69
|
+
| `@angular/forms` | ^21.0.0 | ✅ Yes | Angular reactive & template forms |
|
|
70
|
+
| `@angular/router` | ^21.0.0 | ✅ Yes | Angular routing |
|
|
71
|
+
| `dynamic-ds` | ^1.0.3 | ⚠️ Optional | Icon library (if using icons) |
|
|
62
72
|
|
|
63
73
|
Install peer dependencies if not already present:
|
|
64
74
|
|
|
@@ -66,6 +76,12 @@ Install peer dependencies if not already present:
|
|
|
66
76
|
npm install @angular/common @angular/core @angular/forms @angular/router
|
|
67
77
|
```
|
|
68
78
|
|
|
79
|
+
For icon support, install the optional dependency:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install dynamic-ds
|
|
83
|
+
```
|
|
84
|
+
|
|
69
85
|
---
|
|
70
86
|
|
|
71
87
|
## 🚀 Quick Start
|
|
@@ -83,8 +99,15 @@ import { HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextC
|
|
|
83
99
|
standalone: true,
|
|
84
100
|
imports: [HeaderComponent, SidebarComponent, ButtonContainerComponent, InputTextComponent],
|
|
85
101
|
templateUrl: "./app.component.html",
|
|
102
|
+
styleUrls: ["./app.component.scss"],
|
|
86
103
|
})
|
|
87
|
-
export class AppComponent {
|
|
104
|
+
export class AppComponent {
|
|
105
|
+
username = "";
|
|
106
|
+
|
|
107
|
+
onButtonClick() {
|
|
108
|
+
console.log("Button clicked!");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
88
111
|
```
|
|
89
112
|
|
|
90
113
|
### Step 2: Use in Template
|
|
@@ -96,11 +119,76 @@ export class AppComponent {}
|
|
|
96
119
|
<!-- Sidebar -->
|
|
97
120
|
<app-sidebar [data]="sidebarData"></app-sidebar>
|
|
98
121
|
|
|
99
|
-
<!--
|
|
100
|
-
<
|
|
122
|
+
<!-- Main Content Area -->
|
|
123
|
+
<div class="content">
|
|
124
|
+
<!-- Button -->
|
|
125
|
+
<app-button-container content="Click Me" size="md" backgroundColor="var(--brand-500)" (buttonClick)="onButtonClick()"> </app-button-container>
|
|
126
|
+
|
|
127
|
+
<!-- Input -->
|
|
128
|
+
<app-input-text headerInput="Username" placeholder="Enter your username" [required]="true" [(value)]="username"> </app-input-text>
|
|
129
|
+
</div>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Step 3: Configure Data Objects (Optional)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { HeaderData, SidebarData } from "@goat-bravos/intern-hub-layout";
|
|
136
|
+
|
|
137
|
+
export class AppComponent {
|
|
138
|
+
headerData: HeaderData = {
|
|
139
|
+
headerItems: [
|
|
140
|
+
{
|
|
141
|
+
icon: "dsi-bell-line",
|
|
142
|
+
content: "Notifications",
|
|
143
|
+
badge: "5",
|
|
144
|
+
method: () => console.log("Notifications clicked"),
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
userName: "John Doe",
|
|
148
|
+
logo: "assets/logo.png",
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
sidebarData: SidebarData = {
|
|
152
|
+
backgroundColor: "var(--brand-500)",
|
|
153
|
+
menuItems: [
|
|
154
|
+
{
|
|
155
|
+
iconLeft: "dsi-home-01-line",
|
|
156
|
+
content: "Dashboard",
|
|
157
|
+
url: "/dashboard",
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 📁 Project Structure
|
|
101
167
|
|
|
102
|
-
|
|
103
|
-
|
|
168
|
+
```
|
|
169
|
+
intern-hub-layout/
|
|
170
|
+
├── src/
|
|
171
|
+
│ ├── libs/
|
|
172
|
+
│ │ ├── layouts/ # Layout components
|
|
173
|
+
│ │ │ ├── header/ # Header component
|
|
174
|
+
│ │ │ └── sidebar/ # Sidebar component
|
|
175
|
+
│ │ └── shared/
|
|
176
|
+
│ │ └── components/ # Shared UI components
|
|
177
|
+
│ │ ├── approval/ # Approval list components
|
|
178
|
+
│ │ ├── button/ # Button components
|
|
179
|
+
│ │ ├── file-upload-dropzone/ # Drag & drop file upload
|
|
180
|
+
│ │ ├── functional-label/ # Label with icons
|
|
181
|
+
│ │ ├── icon/ # Icon component
|
|
182
|
+
│ │ ├── input/ # Input components
|
|
183
|
+
│ │ ├── modal/ # Modal dialog
|
|
184
|
+
│ │ ├── pop-up/ # Confirmation dialogs
|
|
185
|
+
│ │ ├── table/ # Table components
|
|
186
|
+
│ │ └── upload-button/ # File upload button
|
|
187
|
+
│ └── public-api.ts # Public API exports
|
|
188
|
+
├── demo/ # Demo application
|
|
189
|
+
├── dist/ # Build output
|
|
190
|
+
├── README.md # This file
|
|
191
|
+
└── package.json # Package configuration
|
|
104
192
|
```
|
|
105
193
|
|
|
106
194
|
---
|
|
@@ -749,11 +837,87 @@ interface ApprovalListItemInterface {
|
|
|
749
837
|
|
|
750
838
|
---
|
|
751
839
|
|
|
840
|
+
### Modal Components
|
|
841
|
+
|
|
842
|
+
#### ModalComponent
|
|
843
|
+
|
|
844
|
+
A flexible modal dialog with customizable themes and responsive design.
|
|
845
|
+
|
|
846
|
+
**Selector:** `app-modal`
|
|
847
|
+
|
|
848
|
+
```typescript
|
|
849
|
+
import { ModalComponent } from "@goat-bravos/intern-hub-layout";
|
|
850
|
+
import { CommonModule } from "@angular/common";
|
|
851
|
+
|
|
852
|
+
@Component({
|
|
853
|
+
imports: [CommonModule, ModalComponent],
|
|
854
|
+
template: `
|
|
855
|
+
<!-- Trigger button -->
|
|
856
|
+
<button (click)="isModalOpen = true">Open Modal</button>
|
|
857
|
+
|
|
858
|
+
<!-- Modal component -->
|
|
859
|
+
@if (isModalOpen) {
|
|
860
|
+
<app-modal [title]="'User Details'" [isOpen]="isModalOpen" [width]="'600px'" [minHeight]="'400px'" [theme]="'default'" (close)="onModalClose()">
|
|
861
|
+
<!-- Modal content goes here -->
|
|
862
|
+
<div class="modal-content">
|
|
863
|
+
<p>This is the modal content area.</p>
|
|
864
|
+
<p>Add any custom content here.</p>
|
|
865
|
+
</div>
|
|
866
|
+
</app-modal>
|
|
867
|
+
}
|
|
868
|
+
`,
|
|
869
|
+
})
|
|
870
|
+
export class MyComponent {
|
|
871
|
+
isModalOpen = false;
|
|
872
|
+
|
|
873
|
+
onModalClose() {
|
|
874
|
+
console.log("Modal closed");
|
|
875
|
+
this.isModalOpen = false;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
**Inputs:**
|
|
881
|
+
|
|
882
|
+
| Input | Type | Default | Description |
|
|
883
|
+
| ----------- | ---------------------- | ----------- | ------------------------- |
|
|
884
|
+
| `title` | `string` | `''` | Modal title text |
|
|
885
|
+
| `width` | `string` | `'800px'` | Modal width |
|
|
886
|
+
| `minHeight` | `string` | `'300px'` | Minimum modal height |
|
|
887
|
+
| `isOpen` | `boolean` | `false` | Controls modal visibility |
|
|
888
|
+
| `theme` | `'default' \| 'white'` | `'default'` | Color theme |
|
|
889
|
+
|
|
890
|
+
**Outputs:**
|
|
891
|
+
|
|
892
|
+
| Output | Type | Description |
|
|
893
|
+
| ------- | -------------------- | --------------------------------- |
|
|
894
|
+
| `close` | `EventEmitter<void>` | Emits when modal should be closed |
|
|
895
|
+
|
|
896
|
+
**Content Projection:**
|
|
897
|
+
|
|
898
|
+
The modal supports content projection. Place any HTML content between the opening and closing tags:
|
|
899
|
+
|
|
900
|
+
```html
|
|
901
|
+
<app-modal [title]="'Custom Modal'" [isOpen]="true" (close)="closeModal()">
|
|
902
|
+
<form>
|
|
903
|
+
<input type="text" placeholder="Name" />
|
|
904
|
+
<button type="submit">Submit</button>
|
|
905
|
+
</form>
|
|
906
|
+
</app-modal>
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
**Themes:**
|
|
910
|
+
|
|
911
|
+
- `default` - Dark themed modal with contrasting colors
|
|
912
|
+
- `white` - Light themed modal with white background
|
|
913
|
+
|
|
914
|
+
---
|
|
915
|
+
|
|
752
916
|
### Pop-up Components
|
|
753
917
|
|
|
754
918
|
#### PopUpConfirmComponent
|
|
755
919
|
|
|
756
|
-
An accessible confirmation modal dialog.
|
|
920
|
+
An accessible confirmation modal dialog for user confirmations.
|
|
757
921
|
|
|
758
922
|
**Selector:** `app-pop-up-confirm`
|
|
759
923
|
|
|
@@ -805,6 +969,124 @@ export class MyComponent {
|
|
|
805
969
|
|
|
806
970
|
---
|
|
807
971
|
|
|
972
|
+
### Upload Components
|
|
973
|
+
|
|
974
|
+
#### UploadButtonComponent
|
|
975
|
+
|
|
976
|
+
A file upload button with label, tooltip support, and helper text.
|
|
977
|
+
|
|
978
|
+
**Selector:** `app-upload-button`
|
|
979
|
+
|
|
980
|
+
```typescript
|
|
981
|
+
import { UploadButtonComponent } from "@goat-bravos/intern-hub-layout";
|
|
982
|
+
|
|
983
|
+
@Component({
|
|
984
|
+
imports: [UploadButtonComponent],
|
|
985
|
+
template: `
|
|
986
|
+
<!-- Basic upload button -->
|
|
987
|
+
<app-upload-button [label]="'Profile Picture'" [required]="true" [buttonText]="'Upload Image'" [acceptFormats]="'.png,.jpg,.jpeg'" [helperText]="'Max size: 5MB (PNG, JPG, JPEG)'" (fileSelected)="onFileSelected($event)"></app-upload-button>
|
|
988
|
+
|
|
989
|
+
<!-- With tooltip -->
|
|
990
|
+
<app-upload-button [label]="'Document Upload'" [showTooltip]="true" [tooltipText]="'Upload your resume or portfolio'" [acceptFormats]="'.pdf,.doc,.docx'" (fileSelected)="onFileSelected($event)"></app-upload-button>
|
|
991
|
+
`,
|
|
992
|
+
})
|
|
993
|
+
export class MyComponent {
|
|
994
|
+
onFileSelected(file: File) {
|
|
995
|
+
console.log("File selected:", file.name, file.size, file.type);
|
|
996
|
+
// Handle file upload logic here
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
**Inputs:**
|
|
1002
|
+
|
|
1003
|
+
| Input | Type | Default | Description |
|
|
1004
|
+
| --------------- | --------- | ------------------------------- | ----------------------------- |
|
|
1005
|
+
| `label` | `string` | `''` | Label text above button |
|
|
1006
|
+
| `required` | `boolean` | `false` | Shows required indicator (\*) |
|
|
1007
|
+
| `showTooltip` | `boolean` | `false` | Shows info tooltip |
|
|
1008
|
+
| `tooltipText` | `string` | `''` | Tooltip content |
|
|
1009
|
+
| `buttonText` | `string` | `'Tải ảnh lên'` | Button text |
|
|
1010
|
+
| `acceptFormats` | `string` | `'.png,.jpeg,.jpg'` | Accepted file formats |
|
|
1011
|
+
| `helperText` | `string` | `'Định dạng .png, .jpeg, .jpg'` | Helper text below button |
|
|
1012
|
+
|
|
1013
|
+
**Outputs:**
|
|
1014
|
+
|
|
1015
|
+
| Output | Type | Description |
|
|
1016
|
+
| -------------- | -------------------- | --------------------------- |
|
|
1017
|
+
| `fileSelected` | `EventEmitter<File>` | Emits when file is selected |
|
|
1018
|
+
|
|
1019
|
+
---
|
|
1020
|
+
|
|
1021
|
+
#### FileUploadDropzoneComponent
|
|
1022
|
+
|
|
1023
|
+
A drag-and-drop file upload zone with multiple file support.
|
|
1024
|
+
|
|
1025
|
+
**Selector:** `app-file-upload-dropzone`
|
|
1026
|
+
|
|
1027
|
+
```typescript
|
|
1028
|
+
import { FileUploadDropzoneComponent } from "@goat-bravos/intern-hub-layout";
|
|
1029
|
+
|
|
1030
|
+
@Component({
|
|
1031
|
+
imports: [FileUploadDropzoneComponent],
|
|
1032
|
+
template: `
|
|
1033
|
+
<!-- Single file upload -->
|
|
1034
|
+
<app-file-upload-dropzone [label]="'Upload Assignment'" [buttonText]="'Browse Files'" [maxSize]="'5MB'" [acceptFormats]="'.pdf,.doc,.docx'" (fileSelected)="onSingleFileSelected($event)"></app-file-upload-dropzone>
|
|
1035
|
+
|
|
1036
|
+
<!-- Multiple files upload -->
|
|
1037
|
+
<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>
|
|
1038
|
+
`,
|
|
1039
|
+
})
|
|
1040
|
+
export class MyComponent {
|
|
1041
|
+
onSingleFileSelected(file: File) {
|
|
1042
|
+
console.log("Single file selected:", file.name);
|
|
1043
|
+
// Handle single file upload
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
onMultipleFilesSelected(files: File[]) {
|
|
1047
|
+
console.log(`${files.length} files selected`);
|
|
1048
|
+
files.forEach((file) => {
|
|
1049
|
+
console.log("File:", file.name, file.size);
|
|
1050
|
+
});
|
|
1051
|
+
// Handle multiple files upload
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
**Inputs:**
|
|
1057
|
+
|
|
1058
|
+
| Input | Type | Default | Description |
|
|
1059
|
+
| --------------- | -------- | --------------------------------------- | ---------------------------- |
|
|
1060
|
+
| `label` | `string` | `'Thêm file bài học'` | Label text above dropzone |
|
|
1061
|
+
| `buttonText` | `string` | `'Tải lên'` | Button text |
|
|
1062
|
+
| `maxSize` | `string` | `'10MB'` | Maximum file size |
|
|
1063
|
+
| `acceptFormats` | `string` | `'.docx,.xlsx,.png,.jpg,.jpeg,.pdf'` | Accepted file formats |
|
|
1064
|
+
| `helperText` | `string` | Auto-generated from maxSize and formats | Helper text (auto or custom) |
|
|
1065
|
+
|
|
1066
|
+
**Outputs:**
|
|
1067
|
+
|
|
1068
|
+
| Output | Type | Description |
|
|
1069
|
+
| --------------- | ---------------------- | -------------------------------------- |
|
|
1070
|
+
| `fileSelected` | `EventEmitter<File>` | Emits when single file is selected |
|
|
1071
|
+
| `filesSelected` | `EventEmitter<File[]>` | Emits when multiple files are selected |
|
|
1072
|
+
|
|
1073
|
+
**Features:**
|
|
1074
|
+
|
|
1075
|
+
- ✅ **Drag & Drop Support** - Users can drag files directly onto the dropzone
|
|
1076
|
+
- ✅ **Visual Feedback** - Highlighted border when dragging files over the zone
|
|
1077
|
+
- ✅ **Multiple Files** - Supports both single and multiple file selection
|
|
1078
|
+
- ✅ **Format Validation** - Restricts file types based on `acceptFormats`
|
|
1079
|
+
- ✅ **Size Display** - Shows maximum allowed file size
|
|
1080
|
+
- ✅ **Accessible** - Keyboard-accessible file input
|
|
1081
|
+
|
|
1082
|
+
**Usage Tips:**
|
|
1083
|
+
|
|
1084
|
+
- The component will emit `fileSelected` for single file uploads
|
|
1085
|
+
- The component will emit `filesSelected` for multiple file uploads
|
|
1086
|
+
- Helper text is automatically generated from `maxSize` and `acceptFormats`, but can be overridden
|
|
1087
|
+
|
|
1088
|
+
---
|
|
1089
|
+
|
|
808
1090
|
### Icon Components
|
|
809
1091
|
|
|
810
1092
|
#### IconComponent
|
|
@@ -903,34 +1185,566 @@ export class MyComponent {
|
|
|
903
1185
|
|
|
904
1186
|
---
|
|
905
1187
|
|
|
1188
|
+
## 💡 Best Practices
|
|
1189
|
+
|
|
1190
|
+
### Component Usage
|
|
1191
|
+
|
|
1192
|
+
#### 1. **Use Two-Way Binding for Forms**
|
|
1193
|
+
|
|
1194
|
+
```typescript
|
|
1195
|
+
// ✅ Good - Two-way binding
|
|
1196
|
+
<app-input-text
|
|
1197
|
+
headerInput="Email"
|
|
1198
|
+
[(value)]="userEmail"
|
|
1199
|
+
></app-input-text>
|
|
1200
|
+
|
|
1201
|
+
// ❌ Avoid - One-way binding without handling value changes
|
|
1202
|
+
<app-input-text
|
|
1203
|
+
headerInput="Email"
|
|
1204
|
+
[value]="userEmail"
|
|
1205
|
+
></app-input-text>
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
#### 2. **Leverage CSS Custom Properties for Theming**
|
|
1209
|
+
|
|
1210
|
+
```typescript
|
|
1211
|
+
// Define your theme colors in global CSS
|
|
1212
|
+
:root {
|
|
1213
|
+
--brand-500: #3b82f6;
|
|
1214
|
+
--brand-600: #2563eb;
|
|
1215
|
+
--neutral-100: #f5f5f5;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// Use them in components
|
|
1219
|
+
<app-button-container
|
|
1220
|
+
content="Submit"
|
|
1221
|
+
backgroundColor="var(--brand-500)"
|
|
1222
|
+
color="var(--neutral-100)"
|
|
1223
|
+
></app-button-container>
|
|
1224
|
+
```
|
|
1225
|
+
|
|
1226
|
+
#### 3. **Import Only What You Need**
|
|
1227
|
+
|
|
1228
|
+
```typescript
|
|
1229
|
+
// ✅ Good - Import only required components
|
|
1230
|
+
import { ButtonContainerComponent, InputTextComponent } from "@goat-bravos/intern-hub-layout";
|
|
1231
|
+
|
|
1232
|
+
// ❌ Avoid - Wildcard imports
|
|
1233
|
+
import * from "@goat-bravos/intern-hub-layout";
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
#### 4. **Use Interfaces for Type Safety**
|
|
1237
|
+
|
|
1238
|
+
```typescript
|
|
1239
|
+
import { HeaderData, SidebarData } from "@goat-bravos/intern-hub-layout";
|
|
1240
|
+
|
|
1241
|
+
export class MyComponent {
|
|
1242
|
+
// ✅ Good - Typed data objects
|
|
1243
|
+
headerData: HeaderData = {
|
|
1244
|
+
headerItems: [],
|
|
1245
|
+
userName: "John Doe",
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// ❌ Avoid - Untyped objects
|
|
1249
|
+
headerData: any = {
|
|
1250
|
+
headerItems: [],
|
|
1251
|
+
userName: "John Doe",
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
#### 5. **Handle Events Properly**
|
|
1257
|
+
|
|
1258
|
+
```typescript
|
|
1259
|
+
// ✅ Good - Proper event handling
|
|
1260
|
+
<app-button-container
|
|
1261
|
+
content="Delete"
|
|
1262
|
+
(buttonClick)="confirmDelete()"
|
|
1263
|
+
></app-button-container>
|
|
1264
|
+
|
|
1265
|
+
confirmDelete() {
|
|
1266
|
+
if (confirm("Are you sure?")) {
|
|
1267
|
+
this.deleteItem();
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// ❌ Avoid - Inline complex logic
|
|
1272
|
+
<app-button-container
|
|
1273
|
+
content="Delete"
|
|
1274
|
+
(buttonClick)="confirm('Are you sure?') && deleteItem()"
|
|
1275
|
+
></app-button-container>
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
### Performance
|
|
1279
|
+
|
|
1280
|
+
- **Use `OnPush` Change Detection**: All library components use `OnPush` for optimal performance
|
|
1281
|
+
- **Avoid Frequent Re-renders**: Pass stable object references to avoid unnecessary re-renders
|
|
1282
|
+
- **Lazy Load Large Components**: Use dynamic imports for modals and heavy components
|
|
1283
|
+
|
|
1284
|
+
### Accessibility
|
|
1285
|
+
|
|
1286
|
+
- **Always Provide Labels**: Use `headerInput` or `label` properties for form elements
|
|
1287
|
+
- **Use Semantic Buttons**: The library components handle semantic HTML automatically
|
|
1288
|
+
- **Test Keyboard Navigation**: Ensure all interactive components are keyboard accessible
|
|
1289
|
+
- **Provide Alt Text**: When using images in headers or icons, provide descriptive text
|
|
1290
|
+
|
|
1291
|
+
---
|
|
1292
|
+
|
|
1293
|
+
## 🔧 Troubleshooting
|
|
1294
|
+
|
|
1295
|
+
### Common Issues
|
|
1296
|
+
|
|
1297
|
+
#### Issue: Components not displaying correctly
|
|
1298
|
+
|
|
1299
|
+
**Possible Causes:**
|
|
1300
|
+
|
|
1301
|
+
- Missing peer dependencies
|
|
1302
|
+
- CSS conflicts with existing styles
|
|
1303
|
+
- Incorrect selector usage
|
|
1304
|
+
|
|
1305
|
+
**Solutions:**
|
|
1306
|
+
|
|
1307
|
+
```bash
|
|
1308
|
+
# Verify all peer dependencies are installed
|
|
1309
|
+
npm list @angular/core @angular/common @angular/forms @angular/router
|
|
1310
|
+
|
|
1311
|
+
# Check package.json for correct versions
|
|
1312
|
+
npm install @angular/common@^21.0.0 @angular/core@^21.0.0
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
#### Issue: Icons not showing
|
|
1316
|
+
|
|
1317
|
+
**Possible Causes:**
|
|
1318
|
+
|
|
1319
|
+
- `dynamic-ds` library not installed
|
|
1320
|
+
- Icon class names incorrect
|
|
1321
|
+
|
|
1322
|
+
**Solutions:**
|
|
1323
|
+
|
|
1324
|
+
```bash
|
|
1325
|
+
# Install the optional icon library
|
|
1326
|
+
npm install dynamic-ds
|
|
1327
|
+
|
|
1328
|
+
# Verify icon names (they should start with 'dsi-')
|
|
1329
|
+
<app-icon icon="dsi-home-01-line"></app-icon>
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
#### Issue: Two-way binding not working
|
|
1333
|
+
|
|
1334
|
+
**Possible Causes:**
|
|
1335
|
+
|
|
1336
|
+
- Missing `FormsModule` import
|
|
1337
|
+
- Incorrect syntax (`[(value)]` vs `[value]`)
|
|
1338
|
+
|
|
1339
|
+
**Solutions:**
|
|
1340
|
+
|
|
1341
|
+
```typescript
|
|
1342
|
+
// Ensure FormsModule is imported
|
|
1343
|
+
import { FormsModule } from '@angular/forms';
|
|
1344
|
+
|
|
1345
|
+
@Component({
|
|
1346
|
+
imports: [FormsModule, InputTextComponent],
|
|
1347
|
+
// ...
|
|
1348
|
+
})
|
|
1349
|
+
|
|
1350
|
+
// Use correct two-way binding syntax
|
|
1351
|
+
<app-input-text [(value)]="myValue"></app-input-text>
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
#### Issue: TypeScript errors about missing interfaces
|
|
1355
|
+
|
|
1356
|
+
**Solutions:**
|
|
1357
|
+
|
|
1358
|
+
```typescript
|
|
1359
|
+
// Import the required interfaces
|
|
1360
|
+
import { HeaderData, SidebarData, ButtonContainerData, IconData } from "@goat-bravos/intern-hub-layout";
|
|
1361
|
+
```
|
|
1362
|
+
|
|
1363
|
+
#### Issue: Sidebar not collapsing/expanding
|
|
1364
|
+
|
|
1365
|
+
**Possible Causes:**
|
|
1366
|
+
|
|
1367
|
+
- Missing router outlet
|
|
1368
|
+
- Incorrect configuration
|
|
1369
|
+
|
|
1370
|
+
**Solutions:**
|
|
1371
|
+
|
|
1372
|
+
```typescript
|
|
1373
|
+
// Ensure Angular Router is properly configured
|
|
1374
|
+
import { RouterOutlet } from '@angular/router';
|
|
1375
|
+
|
|
1376
|
+
@Component({
|
|
1377
|
+
imports: [RouterOutlet, SidebarComponent],
|
|
1378
|
+
template: `
|
|
1379
|
+
<app-sidebar [data]="sidebarData"></app-sidebar>
|
|
1380
|
+
<router-outlet></router-outlet>
|
|
1381
|
+
`
|
|
1382
|
+
})
|
|
1383
|
+
```
|
|
1384
|
+
|
|
1385
|
+
### Getting Help
|
|
1386
|
+
|
|
1387
|
+
If you encounter issues not covered here:
|
|
1388
|
+
|
|
1389
|
+
1. **Check the Demo App**: Review the `/demo` directory for working examples
|
|
1390
|
+
2. **GitHub Issues**: Search for [existing issues](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
|
|
1391
|
+
3. **Create an Issue**: Provide a minimal reproduction example
|
|
1392
|
+
4. **Stack Overflow**: Tag with `angular` and `intern-hub-layout`
|
|
1393
|
+
|
|
1394
|
+
---
|
|
1395
|
+
|
|
1396
|
+
## 📝 Changelog
|
|
1397
|
+
|
|
1398
|
+
### Version 3.0.15 (Current)
|
|
1399
|
+
|
|
1400
|
+
**Added:**
|
|
1401
|
+
|
|
1402
|
+
- ✨ Modal component with theme support
|
|
1403
|
+
- ✨ File upload components (button and dropzone)
|
|
1404
|
+
- ✨ Drag-and-drop file upload functionality
|
|
1405
|
+
- ✨ Enhanced accessibility features
|
|
1406
|
+
|
|
1407
|
+
**Improved:**
|
|
1408
|
+
|
|
1409
|
+
- 🔧 Better TypeScript type definitions
|
|
1410
|
+
- 🔧 Optimized component performance with OnPush
|
|
1411
|
+
- 📚 Comprehensive README documentation
|
|
1412
|
+
|
|
1413
|
+
**Fixed:**
|
|
1414
|
+
|
|
1415
|
+
- 🐛 Icon color inheritance issues
|
|
1416
|
+
- 🐛 Sidebar collapse/expand animations
|
|
1417
|
+
- 🐛 Input validation edge cases
|
|
1418
|
+
|
|
1419
|
+
### Version 3.0.x
|
|
1420
|
+
|
|
1421
|
+
**Added:**
|
|
1422
|
+
|
|
1423
|
+
- Support for Angular 21
|
|
1424
|
+
- Standalone component architecture
|
|
1425
|
+
- Input components (text, stepper, calendar)
|
|
1426
|
+
- Table components with custom templates
|
|
1427
|
+
- Approval list components
|
|
1428
|
+
|
|
1429
|
+
**Changed:**
|
|
1430
|
+
|
|
1431
|
+
- Migrated from NgModules to standalone components
|
|
1432
|
+
- Updated to TypeScript 5.9
|
|
1433
|
+
- Improved CSS architecture
|
|
1434
|
+
|
|
1435
|
+
### Version 2.0.x
|
|
1436
|
+
|
|
1437
|
+
**Added:**
|
|
1438
|
+
|
|
1439
|
+
- Header and sidebar layout components
|
|
1440
|
+
- Button components
|
|
1441
|
+
- Icon support with dynamic-ds
|
|
1442
|
+
|
|
1443
|
+
---
|
|
1444
|
+
|
|
906
1445
|
## 🛠️ Development
|
|
907
1446
|
|
|
1447
|
+
### Prerequisites
|
|
1448
|
+
|
|
1449
|
+
- Node.js (v18 or higher)
|
|
1450
|
+
- npm (v9 or higher)
|
|
1451
|
+
- Angular CLI (v21 or higher)
|
|
1452
|
+
|
|
908
1453
|
### Building the library
|
|
909
1454
|
|
|
1455
|
+
Build the library for production:
|
|
1456
|
+
|
|
910
1457
|
```bash
|
|
911
1458
|
npm run build
|
|
912
1459
|
```
|
|
913
1460
|
|
|
1461
|
+
This will compile the library to the `dist/intern-hub-layout` directory.
|
|
1462
|
+
|
|
914
1463
|
### Running the demo app
|
|
915
1464
|
|
|
1465
|
+
Start the demo application to see all components in action:
|
|
1466
|
+
|
|
916
1467
|
```bash
|
|
917
1468
|
npm run demo
|
|
918
1469
|
```
|
|
919
1470
|
|
|
1471
|
+
Navigate to `http://localhost:4200/` to view the demo.
|
|
1472
|
+
|
|
1473
|
+
### Development Workflow
|
|
1474
|
+
|
|
1475
|
+
1. **Make changes** to components in `src/libs/`
|
|
1476
|
+
2. **Build the library** with `npm run build`
|
|
1477
|
+
3. **Test in demo** app with `npm run demo`
|
|
1478
|
+
4. **Verify build** with `npm run build` after changes
|
|
1479
|
+
|
|
1480
|
+
### Publishing to npm
|
|
1481
|
+
|
|
1482
|
+
#### Dry Run (Test Before Publishing)
|
|
1483
|
+
|
|
1484
|
+
```bash
|
|
1485
|
+
npm run publish:lib:dry
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
This will show what will be published without actually publishing.
|
|
1489
|
+
|
|
1490
|
+
#### Publish to npm Registry
|
|
1491
|
+
|
|
1492
|
+
```bash
|
|
1493
|
+
npm run publish:lib
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
This will:
|
|
1497
|
+
|
|
1498
|
+
1. Build the library
|
|
1499
|
+
2. Navigate to the dist directory
|
|
1500
|
+
3. Publish to npm
|
|
1501
|
+
|
|
1502
|
+
#### Create a Package Tarball
|
|
1503
|
+
|
|
1504
|
+
```bash
|
|
1505
|
+
npm run pack:lib
|
|
1506
|
+
```
|
|
1507
|
+
|
|
1508
|
+
This will:
|
|
1509
|
+
|
|
1510
|
+
1. Increment the patch version
|
|
1511
|
+
2. Build the library
|
|
1512
|
+
3. Create a `.tgz` file for local testing
|
|
1513
|
+
|
|
1514
|
+
### Testing Locally
|
|
1515
|
+
|
|
1516
|
+
To test the library in another Angular project before publishing:
|
|
1517
|
+
|
|
1518
|
+
```bash
|
|
1519
|
+
# In the library project
|
|
1520
|
+
npm run pack:lib
|
|
1521
|
+
|
|
1522
|
+
# In your test project
|
|
1523
|
+
npm install /path/to/intern-hub-layout/dist/intern-hub-layout/goat-bravos-intern-hub-layout-3.0.15.tgz
|
|
1524
|
+
```
|
|
1525
|
+
|
|
1526
|
+
### Project Scripts
|
|
1527
|
+
|
|
1528
|
+
| Script | Description |
|
|
1529
|
+
| ------------------------- | -------------------------------- |
|
|
1530
|
+
| `npm run build` | Build the library for production |
|
|
1531
|
+
| `npm run demo` | Start the demo application |
|
|
1532
|
+
| `npm run publish:lib` | Build and publish to npm |
|
|
1533
|
+
| `npm run publish:lib:dry` | Test publish without uploading |
|
|
1534
|
+
| `npm run pack:lib` | Create a local package tarball |
|
|
1535
|
+
|
|
920
1536
|
---
|
|
921
1537
|
|
|
922
1538
|
## 🤝 Contributing
|
|
923
1539
|
|
|
924
|
-
|
|
1540
|
+
We welcome contributions from the community! Here's how you can help:
|
|
1541
|
+
|
|
1542
|
+
### Getting Started
|
|
1543
|
+
|
|
1544
|
+
1. **Fork the repository**
|
|
1545
|
+
|
|
1546
|
+
```bash
|
|
1547
|
+
git clone https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout.git
|
|
1548
|
+
```
|
|
1549
|
+
|
|
1550
|
+
2. **Create a feature branch**
|
|
1551
|
+
|
|
1552
|
+
```bash
|
|
1553
|
+
git checkout -b feature/AmazingFeature
|
|
1554
|
+
```
|
|
1555
|
+
|
|
1556
|
+
3. **Make your changes**
|
|
1557
|
+
- Follow the existing code style
|
|
1558
|
+
- Add tests if applicable
|
|
1559
|
+
- Update documentation
|
|
1560
|
+
|
|
1561
|
+
4. **Commit your changes**
|
|
1562
|
+
|
|
1563
|
+
```bash
|
|
1564
|
+
git commit -m 'feat: Add some AmazingFeature'
|
|
1565
|
+
```
|
|
1566
|
+
|
|
1567
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
1568
|
+
- `feat:` - New feature
|
|
1569
|
+
- `fix:` - Bug fix
|
|
1570
|
+
- `docs:` - Documentation changes
|
|
1571
|
+
- `style:` - Code style changes (formatting, etc.)
|
|
1572
|
+
- `refactor:` - Code refactoring
|
|
1573
|
+
- `test:` - Adding tests
|
|
1574
|
+
- `chore:` - Maintenance tasks
|
|
1575
|
+
|
|
1576
|
+
5. **Push to your fork**
|
|
1577
|
+
|
|
1578
|
+
```bash
|
|
1579
|
+
git push origin feature/AmazingFeature
|
|
1580
|
+
```
|
|
1581
|
+
|
|
1582
|
+
6. **Open a Pull Request**
|
|
1583
|
+
|
|
1584
|
+
Go to the [repository](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout) and create a pull request.
|
|
1585
|
+
|
|
1586
|
+
### Contribution Guidelines
|
|
1587
|
+
|
|
1588
|
+
#### Code Style
|
|
1589
|
+
|
|
1590
|
+
- Use TypeScript strict mode
|
|
1591
|
+
- Follow Angular style guide
|
|
1592
|
+
- Use meaningful variable and function names
|
|
1593
|
+
- Add comments for complex logic
|
|
1594
|
+
- Keep components focused and single-purpose
|
|
1595
|
+
|
|
1596
|
+
#### Component Guidelines
|
|
1597
|
+
|
|
1598
|
+
When creating a new component:
|
|
1599
|
+
|
|
1600
|
+
1. **Create in appropriate directory**
|
|
1601
|
+
|
|
1602
|
+
```
|
|
1603
|
+
src/libs/shared/components/your-component/
|
|
1604
|
+
├── your-component.component.ts
|
|
1605
|
+
├── your-component.component.html
|
|
1606
|
+
├── your-component.component.scss
|
|
1607
|
+
└── your-component.model.ts (if needed)
|
|
1608
|
+
```
|
|
1609
|
+
|
|
1610
|
+
2. **Use standalone components**
|
|
1611
|
+
|
|
1612
|
+
```typescript
|
|
1613
|
+
@Component({
|
|
1614
|
+
selector: 'app-your-component',
|
|
1615
|
+
standalone: true,
|
|
1616
|
+
imports: [CommonModule],
|
|
1617
|
+
// ...
|
|
1618
|
+
})
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
3. **Export in public-api.ts**
|
|
925
1622
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1623
|
+
```typescript
|
|
1624
|
+
export * from "./libs/shared/components/your-component/your-component.component";
|
|
1625
|
+
```
|
|
1626
|
+
|
|
1627
|
+
4. **Document in README.md**
|
|
1628
|
+
- Add usage examples
|
|
1629
|
+
- Document all inputs and outputs
|
|
1630
|
+
- Include practical examples
|
|
1631
|
+
|
|
1632
|
+
#### Testing
|
|
1633
|
+
|
|
1634
|
+
Before submitting a PR:
|
|
1635
|
+
|
|
1636
|
+
- [ ] Build the library successfully (`npm run build`)
|
|
1637
|
+
- [ ] Test in demo app (`npm run demo`)
|
|
1638
|
+
- [ ] Verify no console errors or warnings
|
|
1639
|
+
- [ ] Test in different browsers (Chrome, Firefox, Safari)
|
|
1640
|
+
- [ ] Check accessibility (keyboard navigation, screen readers)
|
|
1641
|
+
|
|
1642
|
+
#### Pull Request Process
|
|
1643
|
+
|
|
1644
|
+
1. Update the README.md with details of changes
|
|
1645
|
+
2. Update version numbers following [SemVer](https://semver.org/)
|
|
1646
|
+
3. Ensure the PR description clearly describes the problem and solution
|
|
1647
|
+
4. Link any related issues
|
|
1648
|
+
|
|
1649
|
+
### Questions or Issues?
|
|
1650
|
+
|
|
1651
|
+
- Open an [issue](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
|
|
1652
|
+
- Reach out to the maintainers
|
|
1653
|
+
- Check existing issues and PRs first
|
|
931
1654
|
|
|
932
1655
|
---
|
|
933
1656
|
|
|
934
1657
|
## 📄 License
|
|
935
1658
|
|
|
936
|
-
This project is licensed under the MIT License
|
|
1659
|
+
This project is licensed under the **MIT License**.
|
|
1660
|
+
|
|
1661
|
+
### MIT License
|
|
1662
|
+
|
|
1663
|
+
```
|
|
1664
|
+
Copyright (c) 2024 FPT IS Intern Team
|
|
1665
|
+
|
|
1666
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1667
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
1668
|
+
in the Software without restriction, including without limitation the rights
|
|
1669
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1670
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
1671
|
+
furnished to do so, subject to the following conditions:
|
|
1672
|
+
|
|
1673
|
+
The above copyright notice and this permission notice shall be included in all
|
|
1674
|
+
copies or substantial portions of the Software.
|
|
1675
|
+
|
|
1676
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1677
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1678
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1679
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1680
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1681
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1682
|
+
SOFTWARE.
|
|
1683
|
+
```
|
|
1684
|
+
|
|
1685
|
+
---
|
|
1686
|
+
|
|
1687
|
+
## 🔗 Links & Resources
|
|
1688
|
+
|
|
1689
|
+
### Official Links
|
|
1690
|
+
|
|
1691
|
+
- **📦 npm Package**: [@goat-bravos/intern-hub-layout](https://www.npmjs.com/package/@goat-bravos/intern-hub-layout)
|
|
1692
|
+
- **💻 GitHub Repository**: [FPT-IS-Intern/Intern-Hub-FE-Layout](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout)
|
|
1693
|
+
- **📝 Changelog**: [GitHub Releases](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/releases)
|
|
1694
|
+
- **🐛 Bug Reports**: [GitHub Issues](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues)
|
|
1695
|
+
|
|
1696
|
+
### Related Projects
|
|
1697
|
+
|
|
1698
|
+
- **Angular**: [https://angular.dev](https://angular.dev)
|
|
1699
|
+
- **TypeScript**: [https://www.typescriptlang.org](https://www.typescriptlang.org)
|
|
1700
|
+
- **Dynamic DS**: Icon library used by this project
|
|
1701
|
+
|
|
1702
|
+
### External Resources
|
|
1703
|
+
|
|
1704
|
+
- [Angular Style Guide](https://angular.dev/style-guide)
|
|
1705
|
+
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)
|
|
1706
|
+
- [Web Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
1707
|
+
- [Conventional Commits](https://www.conventionalcommits.org/)
|
|
1708
|
+
- [Semantic Versioning](https://semver.org/)
|
|
1709
|
+
|
|
1710
|
+
---
|
|
1711
|
+
|
|
1712
|
+
## 💬 Support
|
|
1713
|
+
|
|
1714
|
+
### Need Help?
|
|
1715
|
+
|
|
1716
|
+
- 💡 **General Questions**: Check the [Troubleshooting](#-troubleshooting) section
|
|
1717
|
+
- 📖 **Documentation**: Read through component examples above
|
|
1718
|
+
- 🐛 **Bug Reports**: [Create an issue](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues/new)
|
|
1719
|
+
- ✨ **Feature Requests**: [Suggest a feature](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/issues/new)
|
|
1720
|
+
- 💬 **Discussions**: [GitHub Discussions](https://github.com/FPT-IS-Intern/Intern-Hub-FE-Layout/discussions)
|
|
1721
|
+
|
|
1722
|
+
### Stay Updated
|
|
1723
|
+
|
|
1724
|
+
- ⭐ Star the repository to stay updated
|
|
1725
|
+
- 👁️ Watch for new releases
|
|
1726
|
+
- 🍴 Fork to contribute
|
|
1727
|
+
|
|
1728
|
+
---
|
|
1729
|
+
|
|
1730
|
+
## 🙏 Acknowledgments
|
|
1731
|
+
|
|
1732
|
+
Built with ❤️ by the **FPT IS Intern Team**
|
|
1733
|
+
|
|
1734
|
+
Special thanks to:
|
|
1735
|
+
|
|
1736
|
+
- The Angular team for an amazing framework
|
|
1737
|
+
- All contributors who help improve this library
|
|
1738
|
+
- The open-source community
|
|
1739
|
+
|
|
1740
|
+
---
|
|
1741
|
+
|
|
1742
|
+
<div align="center">
|
|
1743
|
+
|
|
1744
|
+
**[⬆ Back to Top](#-intern-hub-layout)**
|
|
1745
|
+
|
|
1746
|
+
Made with 💙 by [FPT IS Intern Team](https://github.com/FPT-IS-Intern)
|
|
1747
|
+
|
|
1748
|
+
**📦 @goat-bravos/intern-hub-layout** | **v3.0.15** | **MIT License**
|
|
1749
|
+
|
|
1750
|
+
</div>
|