chrv-components 1.12.21 → 1.12.22
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 +544 -544
- package/chrv-components-1.12.22.tgz +0 -0
- package/fesm2022/chrv-components.mjs +98 -63
- package/fesm2022/chrv-components.mjs.map +1 -1
- package/package.json +1 -1
- package/types/chrv-components.d.ts +15 -2
- package/chrv-components-1.12.21.tgz +0 -0
package/README.md
CHANGED
|
@@ -1,544 +1,544 @@
|
|
|
1
|
-
# 🎨 CHRV Components
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
|
|
5
|
-

|
|
6
|
-

|
|
7
|
-

|
|
8
|
-

|
|
9
|
-
|
|
10
|
-
**Bibliothèque complète de composants Angular avec Tailwind CSS**
|
|
11
|
-
|
|
12
|
-
[📚 Documentation](#-documentation) • [🚀 Installation](#-installation) • [💡 Exemples](#-exemples) • [🛠️ API](#️-api)
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
## ✨ Composants disponibles
|
|
17
|
-
|
|
18
|
-
### 🪟 Système de Modal
|
|
19
|
-
|
|
20
|
-
- **ChrModalComponent** - Modal de base avec backdrop et animations
|
|
21
|
-
- **ModalService** - Service pour gérer les modals avec injection de tokens
|
|
22
|
-
|
|
23
|
-
### 📝 Formulaires et saisie
|
|
24
|
-
|
|
25
|
-
- **ChrFormComponent** - Formulaire dynamique avec sections et contrôles
|
|
26
|
-
- **ChrBaseInputComponent** - Input de base avec validation
|
|
27
|
-
- **ChrColorInputComponent** - Sélecteur de couleur
|
|
28
|
-
- **ChrDateInputComponent** - Input de date
|
|
29
|
-
- **ChrDatetimeInputComponent** - Input de date et heure
|
|
30
|
-
- **ChrFileInputComponent** - Upload de fichiers
|
|
31
|
-
- **ChrNiceFileInputComponent** - Upload de fichiers avec interface améliorée
|
|
32
|
-
- **ChrTextareaInputComponent** - Zone de texte multiligne
|
|
33
|
-
- **ChrToggleInputComponent** - Bouton toggle on/off
|
|
34
|
-
- **ChrSearchSelectComponent** - Sélection avec recherche
|
|
35
|
-
- **ChrTagSelectComponent** - Sélection multiple avec tags
|
|
36
|
-
- **ChrCheckboxComponent** - Case à cocher stylisée
|
|
37
|
-
|
|
38
|
-
### 📊 Affichage de données
|
|
39
|
-
|
|
40
|
-
- **ChrDataTable** - Table de données avec fonctionnalités avancées
|
|
41
|
-
- **ChrTableComponent** - Table avec tri et fonctionnalités
|
|
42
|
-
- **ChrPaginatorComponent** - Pagination avec gestion des cookies
|
|
43
|
-
|
|
44
|
-
### 🎯 Interface utilisateur
|
|
45
|
-
|
|
46
|
-
- **ChrButtonComponent** - Bouton avec icônes et couleurs personnalisables
|
|
47
|
-
- **ChrDropdownComponent** - Menu déroulant avec animation et état vide/ouvert
|
|
48
|
-
- **ChrContextMenuComponent** - Menu contextuel
|
|
49
|
-
- **ChrSpinnerComponent** - Indicateur de chargement
|
|
50
|
-
- **ChrToastComponent** - Notifications toast
|
|
51
|
-
- **ChrInlineSvgComponent** - Affichage SVG inline
|
|
52
|
-
|
|
53
|
-
### 🧭 Navigation
|
|
54
|
-
|
|
55
|
-
- **ChrBreadcrumbComponent** - Fil d'Ariane de navigation
|
|
56
|
-
- **TabComponent** - Onglet individuel
|
|
57
|
-
- **TabGroupComponent** - Groupe d'onglets
|
|
58
|
-
- **CarouselComponent** - Carrousel d'images/contenu
|
|
59
|
-
|
|
60
|
-
### 🎛️ Directives
|
|
61
|
-
|
|
62
|
-
- **TabInputOnlyHandlerDirective** - Gestion navigation par Tab
|
|
63
|
-
- **TabToEnterHandlerDirective** - Conversion Tab vers Enter
|
|
64
|
-
- **AutofocusDirective** - Focus automatique
|
|
65
|
-
- **ChrContextMenuDirective** - Directive pour menus contextuels
|
|
66
|
-
|
|
67
|
-
### 🛠️ Services
|
|
68
|
-
|
|
69
|
-
- **ModalService** - Gestion des modals avec tokens
|
|
70
|
-
- **DialogService** - Service de dialogue
|
|
71
|
-
- **DataService** - Service de données
|
|
72
|
-
- **LiveUpdateService** - Mises à jour en temps réel
|
|
73
|
-
- **LoaderService** - Gestion des états de chargement
|
|
74
|
-
- **ToastService** - Service de notifications
|
|
75
|
-
- **CookieService** - Gestion des cookies
|
|
76
|
-
- **FilesService** - Gestion des fichiers
|
|
77
|
-
|
|
78
|
-
## 🚀 Installation
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# Installation avec toutes les dépendances
|
|
82
|
-
npm install chrv-components
|
|
83
|
-
|
|
84
|
-
# Les dépendances suivantes sont automatiquement incluses :
|
|
85
|
-
# - @angular/material
|
|
86
|
-
# - ngx-pagination
|
|
87
|
-
# - chrv-pipes
|
|
88
|
-
# - @microsoft/signalr
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## ⚙️ Configuration
|
|
92
|
-
|
|
93
|
-
### Import dans votre module Angular
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
import { NgModule } from "@angular/core";
|
|
97
|
-
import { ChrButtonComponent, ChrFormComponent, ChrTableComponent, ModalService } from "chrv-components";
|
|
98
|
-
|
|
99
|
-
@NgModule({
|
|
100
|
-
imports: [ChrButtonComponent, ChrFormComponent, ChrTableComponent],
|
|
101
|
-
providers: [ModalService],
|
|
102
|
-
// ...
|
|
103
|
-
})
|
|
104
|
-
export class AppModule {}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Import dans un composant standalone
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
import { Component } from "@angular/core";
|
|
111
|
-
import { ChrButtonComponent, ChrFormComponent } from "chrv-components";
|
|
112
|
-
|
|
113
|
-
@Component({
|
|
114
|
-
selector: "app-example",
|
|
115
|
-
standalone: true,
|
|
116
|
-
imports: [ChrButtonComponent, ChrFormComponent],
|
|
117
|
-
template: `...`,
|
|
118
|
-
})
|
|
119
|
-
export class ExampleComponent {}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## 💡 Exemples d'utilisation
|
|
123
|
-
|
|
124
|
-
### 🎯 ChrButtonComponent
|
|
125
|
-
|
|
126
|
-
Bouton personnalisable avec icônes et couleurs :
|
|
127
|
-
|
|
128
|
-
```html
|
|
129
|
-
<!-- Bouton simple -->
|
|
130
|
-
<app-chr-button [display]="'Enregistrer'" [color]="'primary'" [click]="saveData"> </app-chr-button>
|
|
131
|
-
|
|
132
|
-
<!-- Bouton avec icône -->
|
|
133
|
-
<app-chr-button [display]="'Supprimer'" [icon]="'delete'" [color]="'warn'" [click]="deleteItem"> </app-chr-button>
|
|
134
|
-
|
|
135
|
-
<!-- Bouton plat -->
|
|
136
|
-
<app-chr-button [display]="'Annuler'" [flat]="true" [click]="cancel"> </app-chr-button>
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 📝 ChrFormComponent
|
|
140
|
-
|
|
141
|
-
Formulaire dynamique basé sur l'interface IControl :
|
|
142
|
-
|
|
143
|
-
**Option 1 : Avec sections**
|
|
144
|
-
|
|
145
|
-
```html
|
|
146
|
-
<app-chr-form [sections]="formSections"></app-chr-form>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
export class FormExampleComponent {
|
|
151
|
-
formSections: IFormSection[] = [
|
|
152
|
-
{
|
|
153
|
-
title: "Informations personnelles",
|
|
154
|
-
controls: [
|
|
155
|
-
{ name: "firstName", type: "text", label: "Prénom" },
|
|
156
|
-
{ name: "lastName", type: "text", label: "Nom" },
|
|
157
|
-
{ name: "email", type: "text", label: "Email" },
|
|
158
|
-
{ name: "birthDate", type: "date", label: "Date de naissance" },
|
|
159
|
-
],
|
|
160
|
-
},
|
|
161
|
-
];
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
**Option 2 : Avec contrôles directement**
|
|
166
|
-
|
|
167
|
-
```html
|
|
168
|
-
<app-chr-form [controls]="formControls"></app-chr-form>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
```typescript
|
|
172
|
-
export class FormExampleComponent {
|
|
173
|
-
formControls: IControl[] = [
|
|
174
|
-
{ name: "firstName", type: "text", label: "Prénom" },
|
|
175
|
-
{ name: "lastName", type: "text", label: "Nom" },
|
|
176
|
-
{ name: "email", type: "text", label: "Email" },
|
|
177
|
-
{ name: "birthDate", type: "date", label: "Date de naissance" },
|
|
178
|
-
];
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### ChrPaginatorComponent
|
|
183
|
-
|
|
184
|
-
Pagination avec gestion automatique :
|
|
185
|
-
|
|
186
|
-
```html
|
|
187
|
-
<app-chr-paginator [id]="'users-pagination'" [page]="currentPage" [pageSize]="itemsPerPage" [allowSizeChange]="true" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)"> </app-chr-paginator>
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
export class PaginationExampleComponent {
|
|
192
|
-
currentPage = 1;
|
|
193
|
-
itemsPerPage = 20;
|
|
194
|
-
|
|
195
|
-
onPageChange(page: number) {
|
|
196
|
-
this.currentPage = page;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
onPageSizeChange(size: number) {
|
|
200
|
-
this.itemsPerPage = size;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### 🪟 ModalService
|
|
206
|
-
|
|
207
|
-
Service pour gérer les modals avec injection de données :
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
import { Component, inject } from "@angular/core";
|
|
211
|
-
import { ModalService, CHR_MODAL_DATA, CHR_MODAL_REF } from "chrv-components";
|
|
212
|
-
|
|
213
|
-
// Composant de modal
|
|
214
|
-
@Component({
|
|
215
|
-
template: `
|
|
216
|
-
<div class="modal-content">
|
|
217
|
-
<h2>{{ data.title }}</h2>
|
|
218
|
-
<p>{{ data.message }}</p>
|
|
219
|
-
<button (click)="close()">Fermer</button>
|
|
220
|
-
</div>
|
|
221
|
-
`,
|
|
222
|
-
})
|
|
223
|
-
export class MyModalComponent {
|
|
224
|
-
data = inject(CHR_MODAL_DATA);
|
|
225
|
-
modalRef = inject(CHR_MODAL_REF);
|
|
226
|
-
|
|
227
|
-
close() {
|
|
228
|
-
this.modalRef.close();
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Utilisation du service
|
|
233
|
-
export class ParentComponent {
|
|
234
|
-
private modalService = inject(ModalService);
|
|
235
|
-
|
|
236
|
-
openModal() {
|
|
237
|
-
this.modalService.open(MyModalComponent, {
|
|
238
|
-
data: {
|
|
239
|
-
title: "Confirmation",
|
|
240
|
-
message: "Êtes-vous sûr de vouloir continuer ?",
|
|
241
|
-
},
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### 🏷️ ChrTagSelectComponent
|
|
248
|
-
|
|
249
|
-
Sélection multiple avec tags :
|
|
250
|
-
|
|
251
|
-
```html
|
|
252
|
-
<chr-tag-select [data]="availableData" [display]="displayFunction" [placeholder]="'Sélectionner des éléments...'" [acceptText]="true"> </chr-tag-select>
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
export class TagSelectExampleComponent {
|
|
257
|
-
availableData = [
|
|
258
|
-
{ id: 1, name: "Option 1" },
|
|
259
|
-
{ id: 2, name: "Option 2" },
|
|
260
|
-
{ id: 3, name: "Option 3" },
|
|
261
|
-
];
|
|
262
|
-
|
|
263
|
-
displayFunction = (item: any) => item.name;
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### 🔄 ChrSpinnerComponent
|
|
268
|
-
|
|
269
|
-
Indicateur de chargement automatique :
|
|
270
|
-
|
|
271
|
-
```html
|
|
272
|
-
<!-- Spinner simple (contrôlé par LoaderService) -->
|
|
273
|
-
<app-chr-spinner></app-chr-spinner>
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
export class SpinnerExampleComponent {
|
|
278
|
-
private loaderService = inject(LoaderService);
|
|
279
|
-
|
|
280
|
-
showSpinner() {
|
|
281
|
-
this.loaderService.show();
|
|
282
|
-
// Simulation d'une tâche
|
|
283
|
-
setTimeout(() => {
|
|
284
|
-
this.loaderService.hide();
|
|
285
|
-
}, 2000);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
## 🛠️ API
|
|
291
|
-
|
|
292
|
-
### ChrButtonComponent
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
@Component({
|
|
296
|
-
inputs: {
|
|
297
|
-
display: string; // Texte du bouton
|
|
298
|
-
icon: string; // Icône Material
|
|
299
|
-
click: Function; // Fonction onClick
|
|
300
|
-
color: Color; // Couleur du bouton
|
|
301
|
-
textColor: Color; // Couleur du texte
|
|
302
|
-
flat: boolean; // Style plat
|
|
303
|
-
}
|
|
304
|
-
})
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### ChrSearchbarComponent
|
|
308
|
-
|
|
309
|
-
```typescript
|
|
310
|
-
@Component({
|
|
311
|
-
inputs: {
|
|
312
|
-
model: string | null; // Valeur actuelle
|
|
313
|
-
placeholder: string | null; // Texte d'aide
|
|
314
|
-
label: string | null; // Label du champ
|
|
315
|
-
},
|
|
316
|
-
outputs: {
|
|
317
|
-
modelChange: string; // Changement de valeur
|
|
318
|
-
}
|
|
319
|
-
})
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### ChrFormComponent
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
@Component({
|
|
326
|
-
inputs: {
|
|
327
|
-
sections: IFormSection[]; // Sections avec contrôles groupés
|
|
328
|
-
controls: IControl[]; // Contrôles directs (utiliser l'un OU l'autre)
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
**Interface IControl :**
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
interface IControl {
|
|
337
|
-
name: string; // Nom unique du contrôle
|
|
338
|
-
type: InputType; // Type d'input
|
|
339
|
-
label?: string; // Label affiché
|
|
340
|
-
value?: any; // Valeur par défaut
|
|
341
|
-
validations?: IControlValidation[]; // Validations
|
|
342
|
-
data?: any[]; // Données pour select/options
|
|
343
|
-
// ... autres propriétés
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
**Interface IFormSection :**
|
|
348
|
-
|
|
349
|
-
```typescript
|
|
350
|
-
interface IFormSection {
|
|
351
|
-
title?: string; // Titre de la section
|
|
352
|
-
controls: IControl[]; // Contrôles de la section
|
|
353
|
-
}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### ChrSearchbarComponent
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
@Component({
|
|
360
|
-
inputs: {
|
|
361
|
-
model: string | null; // Valeur actuelle
|
|
362
|
-
placeholder: string | null; // Texte d'aide
|
|
363
|
-
label: string | null; // Label du champ
|
|
364
|
-
},
|
|
365
|
-
outputs: {
|
|
366
|
-
modelChange: string; // Changement de valeur
|
|
367
|
-
}
|
|
368
|
-
})
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### ChrPaginatorComponent
|
|
372
|
-
|
|
373
|
-
```typescript
|
|
374
|
-
@Component({
|
|
375
|
-
inputs: {
|
|
376
|
-
page: number; // Page actuelle
|
|
377
|
-
pageSize: number; // Nombre d'éléments par page
|
|
378
|
-
id: string; // ID unique du paginateur
|
|
379
|
-
allowSizeChange: boolean | string; // Permet de changer la taille
|
|
380
|
-
},
|
|
381
|
-
outputs: {
|
|
382
|
-
pageChange: number; // Changement de page
|
|
383
|
-
pageSizeChange: number; // Changement de taille
|
|
384
|
-
}
|
|
385
|
-
})
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
### ChrTagSelectComponent
|
|
389
|
-
|
|
390
|
-
```typescript
|
|
391
|
-
@Component({
|
|
392
|
-
inputs: {
|
|
393
|
-
placeholder: string; // Texte d'aide dans l'input
|
|
394
|
-
data: any[] | null; // Données pour l'autocomplete
|
|
395
|
-
display: (entry: any) => string; // Fonction d'affichage
|
|
396
|
-
filters: IInputSearchFilter[] | null; // Filtres de recherche
|
|
397
|
-
editCallback: Function; // Callback de modification
|
|
398
|
-
addCallback: Function; // Callback d'ajout
|
|
399
|
-
removeCallback: Function; // Callback de suppression
|
|
400
|
-
acceptText: boolean | null; // Accepte le texte libre
|
|
401
|
-
}
|
|
402
|
-
})
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
### ModalService
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
class ModalService {
|
|
409
|
-
open<T>(component: ComponentType<T>, options?: ModalOptions): void;
|
|
410
|
-
close(): void;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
interface ModalOptions {
|
|
414
|
-
closeOnBackdropClick?: boolean;
|
|
415
|
-
closeOnEscape?: boolean;
|
|
416
|
-
width?: number;
|
|
417
|
-
height?: number;
|
|
418
|
-
data?: any; // Données injectées via CHR_MODAL_DATA
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
## 🎨 Thèmes et personnalisation
|
|
423
|
-
|
|
424
|
-
### Variables CSS disponibles
|
|
425
|
-
|
|
426
|
-
Les composants utilisent un système de variables CSS pour les couleurs. Vous pouvez les personnaliser en redéfinissant ces variables :
|
|
427
|
-
|
|
428
|
-
```css
|
|
429
|
-
:root {
|
|
430
|
-
--primary-color: #your-color;
|
|
431
|
-
--primary-contrast-color: #your-contrast-color;
|
|
432
|
-
--secondary-color: #your-secondary;
|
|
433
|
-
--secondary-contrast-color: #your-secondary-contrast;
|
|
434
|
-
--tertiary-color: #your-tertiary;
|
|
435
|
-
--tertiary-contrast-color: #your-tertiary-contrast;
|
|
436
|
-
--warn-color: #your-warn;
|
|
437
|
-
--warn-contrast-color: #your-warn-contrast;
|
|
438
|
-
--error-color: #your-error;
|
|
439
|
-
--error-contrast-color: #your-error-contrast;
|
|
440
|
-
--neutral-color: #your-neutral;
|
|
441
|
-
--text-color: #your-text;
|
|
442
|
-
--text-neutral-color: #your-text-neutral;
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### Classes CSS disponibles
|
|
447
|
-
|
|
448
|
-
La bibliothèque fournit des classes utilitaires pour les couleurs :
|
|
449
|
-
|
|
450
|
-
```css
|
|
451
|
-
/* Arrière-plans */
|
|
452
|
-
.bg-primary, .bg-secondary, .bg-tertiary, .bg-warn, .bg-error, .bg-neutral
|
|
453
|
-
.bg-primary-contrast, .bg-secondary-contrast, .bg-tertiary-contrast, .bg-warn-contrast, .bg-error-contrast
|
|
454
|
-
|
|
455
|
-
/* Texte */
|
|
456
|
-
.text-primary, .text-secondary, .text-tertiary, .text-warn, .text-error, .text-neutral
|
|
457
|
-
.text-primary-contrast, .text-secondary-contrast, .text-tertiary-contrast, .text-warn-contrast, .text-error-contrast
|
|
458
|
-
|
|
459
|
-
/* Bordures */
|
|
460
|
-
.border-primary, .border-secondary, .border-tertiary, .border-warn, .border-error
|
|
461
|
-
.border-primary-contrast, .border-secondary-contrast, .border-tertiary-contrast, .border-warn-contrast, .border-error-contrast;
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Personnalisation avancée avec ::ng-deep
|
|
465
|
-
|
|
466
|
-
Pour modifier les styles des composants compilés, utilisez `::ng-deep` :
|
|
467
|
-
|
|
468
|
-
```scss
|
|
469
|
-
// Dans votre composant .scss
|
|
470
|
-
::ng-deep .chr-button {
|
|
471
|
-
border-radius: 8px;
|
|
472
|
-
font-weight: 600;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
::ng-deep .chr-form .form-field {
|
|
476
|
-
margin-bottom: 16px;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
::ng-deep .chr-modal .modal-backdrop {
|
|
480
|
-
background-color: rgba(0, 0, 0, 0.8);
|
|
481
|
-
}
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
### Exemple de thème personnalisé
|
|
485
|
-
|
|
486
|
-
```css
|
|
487
|
-
/* Thème sombre personnalisé */
|
|
488
|
-
:root {
|
|
489
|
-
--primary-color: #3b82f6;
|
|
490
|
-
--primary-contrast-color: #ffffff;
|
|
491
|
-
--secondary-color: #6b7280;
|
|
492
|
-
--secondary-contrast-color: #ffffff;
|
|
493
|
-
--tertiary-color: #f3f4f6;
|
|
494
|
-
--tertiary-contrast-color: #1f2937;
|
|
495
|
-
--warn-color: #f59e0b;
|
|
496
|
-
--warn-contrast-color: #ffffff;
|
|
497
|
-
--error-color: #ef4444;
|
|
498
|
-
--error-contrast-color: #ffffff;
|
|
499
|
-
--neutral-color: #e5e7eb;
|
|
500
|
-
--text-color: #1f2937;
|
|
501
|
-
--text-neutral-color: #6b7280;
|
|
502
|
-
}
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
## 📦 Intégrations
|
|
506
|
-
|
|
507
|
-
### Dépendances automatiques
|
|
508
|
-
|
|
509
|
-
- **Angular Material** - Composants Material Design
|
|
510
|
-
- **ngx-pagination** - Pagination avancée
|
|
511
|
-
- **chrv-pipes** - Pipes utilitaires
|
|
512
|
-
- **@microsoft/signalr** - Communication temps réel
|
|
513
|
-
- **ngx-mask** - Masques de saisie
|
|
514
|
-
|
|
515
|
-
### Interceptors et providers
|
|
516
|
-
|
|
517
|
-
```typescript
|
|
518
|
-
// Configuration automatique des interceptors
|
|
519
|
-
import {
|
|
520
|
-
SpinnerInterceptor,
|
|
521
|
-
XsrfInterceptor,
|
|
522
|
-
xsrfProvider
|
|
523
|
-
} from 'chrv-components';
|
|
524
|
-
|
|
525
|
-
@NgModule({
|
|
526
|
-
providers: [
|
|
527
|
-
xsrfProvider,
|
|
528
|
-
{ provide: HTTP_INTERCEPTORS, useClass: SpinnerInterceptor, multi: true },
|
|
529
|
-
{ provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor, multi: true }
|
|
530
|
-
]
|
|
531
|
-
})
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
## 📝 Notes
|
|
535
|
-
|
|
536
|
-
- Compatible Angular 16+
|
|
537
|
-
- Composants standalone prêts pour le tree-shaking
|
|
538
|
-
- Types TypeScript complets
|
|
539
|
-
- Intégration Tailwind CSS native
|
|
540
|
-
- Support des signaux Angular modernes
|
|
541
|
-
|
|
542
|
-
## 📄 Licence
|
|
543
|
-
|
|
544
|
-
MIT © CHRV Components
|
|
1
|
+
# 🎨 CHRV Components
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
**Bibliothèque complète de composants Angular avec Tailwind CSS**
|
|
11
|
+
|
|
12
|
+
[📚 Documentation](#-documentation) • [🚀 Installation](#-installation) • [💡 Exemples](#-exemples) • [🛠️ API](#️-api)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
## ✨ Composants disponibles
|
|
17
|
+
|
|
18
|
+
### 🪟 Système de Modal
|
|
19
|
+
|
|
20
|
+
- **ChrModalComponent** - Modal de base avec backdrop et animations
|
|
21
|
+
- **ModalService** - Service pour gérer les modals avec injection de tokens
|
|
22
|
+
|
|
23
|
+
### 📝 Formulaires et saisie
|
|
24
|
+
|
|
25
|
+
- **ChrFormComponent** - Formulaire dynamique avec sections et contrôles
|
|
26
|
+
- **ChrBaseInputComponent** - Input de base avec validation
|
|
27
|
+
- **ChrColorInputComponent** - Sélecteur de couleur
|
|
28
|
+
- **ChrDateInputComponent** - Input de date
|
|
29
|
+
- **ChrDatetimeInputComponent** - Input de date et heure
|
|
30
|
+
- **ChrFileInputComponent** - Upload de fichiers
|
|
31
|
+
- **ChrNiceFileInputComponent** - Upload de fichiers avec interface améliorée
|
|
32
|
+
- **ChrTextareaInputComponent** - Zone de texte multiligne
|
|
33
|
+
- **ChrToggleInputComponent** - Bouton toggle on/off
|
|
34
|
+
- **ChrSearchSelectComponent** - Sélection avec recherche
|
|
35
|
+
- **ChrTagSelectComponent** - Sélection multiple avec tags
|
|
36
|
+
- **ChrCheckboxComponent** - Case à cocher stylisée
|
|
37
|
+
|
|
38
|
+
### 📊 Affichage de données
|
|
39
|
+
|
|
40
|
+
- **ChrDataTable** - Table de données avec fonctionnalités avancées
|
|
41
|
+
- **ChrTableComponent** - Table avec tri et fonctionnalités
|
|
42
|
+
- **ChrPaginatorComponent** - Pagination avec gestion des cookies
|
|
43
|
+
|
|
44
|
+
### 🎯 Interface utilisateur
|
|
45
|
+
|
|
46
|
+
- **ChrButtonComponent** - Bouton avec icônes et couleurs personnalisables
|
|
47
|
+
- **ChrDropdownComponent** - Menu déroulant avec animation et état vide/ouvert
|
|
48
|
+
- **ChrContextMenuComponent** - Menu contextuel
|
|
49
|
+
- **ChrSpinnerComponent** - Indicateur de chargement
|
|
50
|
+
- **ChrToastComponent** - Notifications toast
|
|
51
|
+
- **ChrInlineSvgComponent** - Affichage SVG inline
|
|
52
|
+
|
|
53
|
+
### 🧭 Navigation
|
|
54
|
+
|
|
55
|
+
- **ChrBreadcrumbComponent** - Fil d'Ariane de navigation
|
|
56
|
+
- **TabComponent** - Onglet individuel
|
|
57
|
+
- **TabGroupComponent** - Groupe d'onglets
|
|
58
|
+
- **CarouselComponent** - Carrousel d'images/contenu
|
|
59
|
+
|
|
60
|
+
### 🎛️ Directives
|
|
61
|
+
|
|
62
|
+
- **TabInputOnlyHandlerDirective** - Gestion navigation par Tab
|
|
63
|
+
- **TabToEnterHandlerDirective** - Conversion Tab vers Enter
|
|
64
|
+
- **AutofocusDirective** - Focus automatique
|
|
65
|
+
- **ChrContextMenuDirective** - Directive pour menus contextuels
|
|
66
|
+
|
|
67
|
+
### 🛠️ Services
|
|
68
|
+
|
|
69
|
+
- **ModalService** - Gestion des modals avec tokens
|
|
70
|
+
- **DialogService** - Service de dialogue
|
|
71
|
+
- **DataService** - Service de données
|
|
72
|
+
- **LiveUpdateService** - Mises à jour en temps réel
|
|
73
|
+
- **LoaderService** - Gestion des états de chargement
|
|
74
|
+
- **ToastService** - Service de notifications
|
|
75
|
+
- **CookieService** - Gestion des cookies
|
|
76
|
+
- **FilesService** - Gestion des fichiers
|
|
77
|
+
|
|
78
|
+
## 🚀 Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Installation avec toutes les dépendances
|
|
82
|
+
npm install chrv-components
|
|
83
|
+
|
|
84
|
+
# Les dépendances suivantes sont automatiquement incluses :
|
|
85
|
+
# - @angular/material
|
|
86
|
+
# - ngx-pagination
|
|
87
|
+
# - chrv-pipes
|
|
88
|
+
# - @microsoft/signalr
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## ⚙️ Configuration
|
|
92
|
+
|
|
93
|
+
### Import dans votre module Angular
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { NgModule } from "@angular/core";
|
|
97
|
+
import { ChrButtonComponent, ChrFormComponent, ChrTableComponent, ModalService } from "chrv-components";
|
|
98
|
+
|
|
99
|
+
@NgModule({
|
|
100
|
+
imports: [ChrButtonComponent, ChrFormComponent, ChrTableComponent],
|
|
101
|
+
providers: [ModalService],
|
|
102
|
+
// ...
|
|
103
|
+
})
|
|
104
|
+
export class AppModule {}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Import dans un composant standalone
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { Component } from "@angular/core";
|
|
111
|
+
import { ChrButtonComponent, ChrFormComponent } from "chrv-components";
|
|
112
|
+
|
|
113
|
+
@Component({
|
|
114
|
+
selector: "app-example",
|
|
115
|
+
standalone: true,
|
|
116
|
+
imports: [ChrButtonComponent, ChrFormComponent],
|
|
117
|
+
template: `...`,
|
|
118
|
+
})
|
|
119
|
+
export class ExampleComponent {}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 💡 Exemples d'utilisation
|
|
123
|
+
|
|
124
|
+
### 🎯 ChrButtonComponent
|
|
125
|
+
|
|
126
|
+
Bouton personnalisable avec icônes et couleurs :
|
|
127
|
+
|
|
128
|
+
```html
|
|
129
|
+
<!-- Bouton simple -->
|
|
130
|
+
<app-chr-button [display]="'Enregistrer'" [color]="'primary'" [click]="saveData"> </app-chr-button>
|
|
131
|
+
|
|
132
|
+
<!-- Bouton avec icône -->
|
|
133
|
+
<app-chr-button [display]="'Supprimer'" [icon]="'delete'" [color]="'warn'" [click]="deleteItem"> </app-chr-button>
|
|
134
|
+
|
|
135
|
+
<!-- Bouton plat -->
|
|
136
|
+
<app-chr-button [display]="'Annuler'" [flat]="true" [click]="cancel"> </app-chr-button>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 📝 ChrFormComponent
|
|
140
|
+
|
|
141
|
+
Formulaire dynamique basé sur l'interface IControl :
|
|
142
|
+
|
|
143
|
+
**Option 1 : Avec sections**
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<app-chr-form [sections]="formSections"></app-chr-form>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
export class FormExampleComponent {
|
|
151
|
+
formSections: IFormSection[] = [
|
|
152
|
+
{
|
|
153
|
+
title: "Informations personnelles",
|
|
154
|
+
controls: [
|
|
155
|
+
{ name: "firstName", type: "text", label: "Prénom" },
|
|
156
|
+
{ name: "lastName", type: "text", label: "Nom" },
|
|
157
|
+
{ name: "email", type: "text", label: "Email" },
|
|
158
|
+
{ name: "birthDate", type: "date", label: "Date de naissance" },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Option 2 : Avec contrôles directement**
|
|
166
|
+
|
|
167
|
+
```html
|
|
168
|
+
<app-chr-form [controls]="formControls"></app-chr-form>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
export class FormExampleComponent {
|
|
173
|
+
formControls: IControl[] = [
|
|
174
|
+
{ name: "firstName", type: "text", label: "Prénom" },
|
|
175
|
+
{ name: "lastName", type: "text", label: "Nom" },
|
|
176
|
+
{ name: "email", type: "text", label: "Email" },
|
|
177
|
+
{ name: "birthDate", type: "date", label: "Date de naissance" },
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### ChrPaginatorComponent
|
|
183
|
+
|
|
184
|
+
Pagination avec gestion automatique :
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<app-chr-paginator [id]="'users-pagination'" [page]="currentPage" [pageSize]="itemsPerPage" [allowSizeChange]="true" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)"> </app-chr-paginator>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
export class PaginationExampleComponent {
|
|
192
|
+
currentPage = 1;
|
|
193
|
+
itemsPerPage = 20;
|
|
194
|
+
|
|
195
|
+
onPageChange(page: number) {
|
|
196
|
+
this.currentPage = page;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
onPageSizeChange(size: number) {
|
|
200
|
+
this.itemsPerPage = size;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 🪟 ModalService
|
|
206
|
+
|
|
207
|
+
Service pour gérer les modals avec injection de données :
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { Component, inject } from "@angular/core";
|
|
211
|
+
import { ModalService, CHR_MODAL_DATA, CHR_MODAL_REF } from "chrv-components";
|
|
212
|
+
|
|
213
|
+
// Composant de modal
|
|
214
|
+
@Component({
|
|
215
|
+
template: `
|
|
216
|
+
<div class="modal-content">
|
|
217
|
+
<h2>{{ data.title }}</h2>
|
|
218
|
+
<p>{{ data.message }}</p>
|
|
219
|
+
<button (click)="close()">Fermer</button>
|
|
220
|
+
</div>
|
|
221
|
+
`,
|
|
222
|
+
})
|
|
223
|
+
export class MyModalComponent {
|
|
224
|
+
data = inject(CHR_MODAL_DATA);
|
|
225
|
+
modalRef = inject(CHR_MODAL_REF);
|
|
226
|
+
|
|
227
|
+
close() {
|
|
228
|
+
this.modalRef.close();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Utilisation du service
|
|
233
|
+
export class ParentComponent {
|
|
234
|
+
private modalService = inject(ModalService);
|
|
235
|
+
|
|
236
|
+
openModal() {
|
|
237
|
+
this.modalService.open(MyModalComponent, {
|
|
238
|
+
data: {
|
|
239
|
+
title: "Confirmation",
|
|
240
|
+
message: "Êtes-vous sûr de vouloir continuer ?",
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### 🏷️ ChrTagSelectComponent
|
|
248
|
+
|
|
249
|
+
Sélection multiple avec tags :
|
|
250
|
+
|
|
251
|
+
```html
|
|
252
|
+
<chr-tag-select [data]="availableData" [display]="displayFunction" [placeholder]="'Sélectionner des éléments...'" [acceptText]="true"> </chr-tag-select>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
export class TagSelectExampleComponent {
|
|
257
|
+
availableData = [
|
|
258
|
+
{ id: 1, name: "Option 1" },
|
|
259
|
+
{ id: 2, name: "Option 2" },
|
|
260
|
+
{ id: 3, name: "Option 3" },
|
|
261
|
+
];
|
|
262
|
+
|
|
263
|
+
displayFunction = (item: any) => item.name;
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 🔄 ChrSpinnerComponent
|
|
268
|
+
|
|
269
|
+
Indicateur de chargement automatique :
|
|
270
|
+
|
|
271
|
+
```html
|
|
272
|
+
<!-- Spinner simple (contrôlé par LoaderService) -->
|
|
273
|
+
<app-chr-spinner></app-chr-spinner>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
export class SpinnerExampleComponent {
|
|
278
|
+
private loaderService = inject(LoaderService);
|
|
279
|
+
|
|
280
|
+
showSpinner() {
|
|
281
|
+
this.loaderService.show();
|
|
282
|
+
// Simulation d'une tâche
|
|
283
|
+
setTimeout(() => {
|
|
284
|
+
this.loaderService.hide();
|
|
285
|
+
}, 2000);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 🛠️ API
|
|
291
|
+
|
|
292
|
+
### ChrButtonComponent
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
@Component({
|
|
296
|
+
inputs: {
|
|
297
|
+
display: string; // Texte du bouton
|
|
298
|
+
icon: string; // Icône Material
|
|
299
|
+
click: Function; // Fonction onClick
|
|
300
|
+
color: Color; // Couleur du bouton
|
|
301
|
+
textColor: Color; // Couleur du texte
|
|
302
|
+
flat: boolean; // Style plat
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### ChrSearchbarComponent
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
@Component({
|
|
311
|
+
inputs: {
|
|
312
|
+
model: string | null; // Valeur actuelle
|
|
313
|
+
placeholder: string | null; // Texte d'aide
|
|
314
|
+
label: string | null; // Label du champ
|
|
315
|
+
},
|
|
316
|
+
outputs: {
|
|
317
|
+
modelChange: string; // Changement de valeur
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### ChrFormComponent
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
@Component({
|
|
326
|
+
inputs: {
|
|
327
|
+
sections: IFormSection[]; // Sections avec contrôles groupés
|
|
328
|
+
controls: IControl[]; // Contrôles directs (utiliser l'un OU l'autre)
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Interface IControl :**
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
interface IControl {
|
|
337
|
+
name: string; // Nom unique du contrôle
|
|
338
|
+
type: InputType; // Type d'input
|
|
339
|
+
label?: string; // Label affiché
|
|
340
|
+
value?: any; // Valeur par défaut
|
|
341
|
+
validations?: IControlValidation[]; // Validations
|
|
342
|
+
data?: any[]; // Données pour select/options
|
|
343
|
+
// ... autres propriétés
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Interface IFormSection :**
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
interface IFormSection {
|
|
351
|
+
title?: string; // Titre de la section
|
|
352
|
+
controls: IControl[]; // Contrôles de la section
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### ChrSearchbarComponent
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
@Component({
|
|
360
|
+
inputs: {
|
|
361
|
+
model: string | null; // Valeur actuelle
|
|
362
|
+
placeholder: string | null; // Texte d'aide
|
|
363
|
+
label: string | null; // Label du champ
|
|
364
|
+
},
|
|
365
|
+
outputs: {
|
|
366
|
+
modelChange: string; // Changement de valeur
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### ChrPaginatorComponent
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
@Component({
|
|
375
|
+
inputs: {
|
|
376
|
+
page: number; // Page actuelle
|
|
377
|
+
pageSize: number; // Nombre d'éléments par page
|
|
378
|
+
id: string; // ID unique du paginateur
|
|
379
|
+
allowSizeChange: boolean | string; // Permet de changer la taille
|
|
380
|
+
},
|
|
381
|
+
outputs: {
|
|
382
|
+
pageChange: number; // Changement de page
|
|
383
|
+
pageSizeChange: number; // Changement de taille
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### ChrTagSelectComponent
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
@Component({
|
|
392
|
+
inputs: {
|
|
393
|
+
placeholder: string; // Texte d'aide dans l'input
|
|
394
|
+
data: any[] | null; // Données pour l'autocomplete
|
|
395
|
+
display: (entry: any) => string; // Fonction d'affichage
|
|
396
|
+
filters: IInputSearchFilter[] | null; // Filtres de recherche
|
|
397
|
+
editCallback: Function; // Callback de modification
|
|
398
|
+
addCallback: Function; // Callback d'ajout
|
|
399
|
+
removeCallback: Function; // Callback de suppression
|
|
400
|
+
acceptText: boolean | null; // Accepte le texte libre
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### ModalService
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
class ModalService {
|
|
409
|
+
open<T>(component: ComponentType<T>, options?: ModalOptions): void;
|
|
410
|
+
close(): void;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
interface ModalOptions {
|
|
414
|
+
closeOnBackdropClick?: boolean;
|
|
415
|
+
closeOnEscape?: boolean;
|
|
416
|
+
width?: number;
|
|
417
|
+
height?: number;
|
|
418
|
+
data?: any; // Données injectées via CHR_MODAL_DATA
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## 🎨 Thèmes et personnalisation
|
|
423
|
+
|
|
424
|
+
### Variables CSS disponibles
|
|
425
|
+
|
|
426
|
+
Les composants utilisent un système de variables CSS pour les couleurs. Vous pouvez les personnaliser en redéfinissant ces variables :
|
|
427
|
+
|
|
428
|
+
```css
|
|
429
|
+
:root {
|
|
430
|
+
--primary-color: #your-color;
|
|
431
|
+
--primary-contrast-color: #your-contrast-color;
|
|
432
|
+
--secondary-color: #your-secondary;
|
|
433
|
+
--secondary-contrast-color: #your-secondary-contrast;
|
|
434
|
+
--tertiary-color: #your-tertiary;
|
|
435
|
+
--tertiary-contrast-color: #your-tertiary-contrast;
|
|
436
|
+
--warn-color: #your-warn;
|
|
437
|
+
--warn-contrast-color: #your-warn-contrast;
|
|
438
|
+
--error-color: #your-error;
|
|
439
|
+
--error-contrast-color: #your-error-contrast;
|
|
440
|
+
--neutral-color: #your-neutral;
|
|
441
|
+
--text-color: #your-text;
|
|
442
|
+
--text-neutral-color: #your-text-neutral;
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Classes CSS disponibles
|
|
447
|
+
|
|
448
|
+
La bibliothèque fournit des classes utilitaires pour les couleurs :
|
|
449
|
+
|
|
450
|
+
```css
|
|
451
|
+
/* Arrière-plans */
|
|
452
|
+
.bg-primary, .bg-secondary, .bg-tertiary, .bg-warn, .bg-error, .bg-neutral
|
|
453
|
+
.bg-primary-contrast, .bg-secondary-contrast, .bg-tertiary-contrast, .bg-warn-contrast, .bg-error-contrast
|
|
454
|
+
|
|
455
|
+
/* Texte */
|
|
456
|
+
.text-primary, .text-secondary, .text-tertiary, .text-warn, .text-error, .text-neutral
|
|
457
|
+
.text-primary-contrast, .text-secondary-contrast, .text-tertiary-contrast, .text-warn-contrast, .text-error-contrast
|
|
458
|
+
|
|
459
|
+
/* Bordures */
|
|
460
|
+
.border-primary, .border-secondary, .border-tertiary, .border-warn, .border-error
|
|
461
|
+
.border-primary-contrast, .border-secondary-contrast, .border-tertiary-contrast, .border-warn-contrast, .border-error-contrast;
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Personnalisation avancée avec ::ng-deep
|
|
465
|
+
|
|
466
|
+
Pour modifier les styles des composants compilés, utilisez `::ng-deep` :
|
|
467
|
+
|
|
468
|
+
```scss
|
|
469
|
+
// Dans votre composant .scss
|
|
470
|
+
::ng-deep .chr-button {
|
|
471
|
+
border-radius: 8px;
|
|
472
|
+
font-weight: 600;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
::ng-deep .chr-form .form-field {
|
|
476
|
+
margin-bottom: 16px;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
::ng-deep .chr-modal .modal-backdrop {
|
|
480
|
+
background-color: rgba(0, 0, 0, 0.8);
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Exemple de thème personnalisé
|
|
485
|
+
|
|
486
|
+
```css
|
|
487
|
+
/* Thème sombre personnalisé */
|
|
488
|
+
:root {
|
|
489
|
+
--primary-color: #3b82f6;
|
|
490
|
+
--primary-contrast-color: #ffffff;
|
|
491
|
+
--secondary-color: #6b7280;
|
|
492
|
+
--secondary-contrast-color: #ffffff;
|
|
493
|
+
--tertiary-color: #f3f4f6;
|
|
494
|
+
--tertiary-contrast-color: #1f2937;
|
|
495
|
+
--warn-color: #f59e0b;
|
|
496
|
+
--warn-contrast-color: #ffffff;
|
|
497
|
+
--error-color: #ef4444;
|
|
498
|
+
--error-contrast-color: #ffffff;
|
|
499
|
+
--neutral-color: #e5e7eb;
|
|
500
|
+
--text-color: #1f2937;
|
|
501
|
+
--text-neutral-color: #6b7280;
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## 📦 Intégrations
|
|
506
|
+
|
|
507
|
+
### Dépendances automatiques
|
|
508
|
+
|
|
509
|
+
- **Angular Material** - Composants Material Design
|
|
510
|
+
- **ngx-pagination** - Pagination avancée
|
|
511
|
+
- **chrv-pipes** - Pipes utilitaires
|
|
512
|
+
- **@microsoft/signalr** - Communication temps réel
|
|
513
|
+
- **ngx-mask** - Masques de saisie
|
|
514
|
+
|
|
515
|
+
### Interceptors et providers
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
// Configuration automatique des interceptors
|
|
519
|
+
import {
|
|
520
|
+
SpinnerInterceptor,
|
|
521
|
+
XsrfInterceptor,
|
|
522
|
+
xsrfProvider
|
|
523
|
+
} from 'chrv-components';
|
|
524
|
+
|
|
525
|
+
@NgModule({
|
|
526
|
+
providers: [
|
|
527
|
+
xsrfProvider,
|
|
528
|
+
{ provide: HTTP_INTERCEPTORS, useClass: SpinnerInterceptor, multi: true },
|
|
529
|
+
{ provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor, multi: true }
|
|
530
|
+
]
|
|
531
|
+
})
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
## 📝 Notes
|
|
535
|
+
|
|
536
|
+
- Compatible Angular 16+
|
|
537
|
+
- Composants standalone prêts pour le tree-shaking
|
|
538
|
+
- Types TypeScript complets
|
|
539
|
+
- Intégration Tailwind CSS native
|
|
540
|
+
- Support des signaux Angular modernes
|
|
541
|
+
|
|
542
|
+
## 📄 Licence
|
|
543
|
+
|
|
544
|
+
MIT © CHRV Components
|