@cityway/bo-ui 1.1.0-beta003 → 1.1.0-beta005

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.
Binary file
Binary file
@@ -32,12 +32,16 @@ En-tête de page transverse du back-office. Couvre :
32
32
  | `actions` | `PageHeaderActionEnum[]` | `[]` | Liste des actions à afficher. Voir enum §3. L'ordre d'affichage est imposé par le template (cf. §5). |
33
33
  | `isLoading` | `PageHeaderActionState` | `{}` | Map action → `boolean` ; passe l'action en état chargement. |
34
34
  | `isDisabled` | `PageHeaderActionState` | `{}` | Map action → `boolean` ; désactive l'action. |
35
+ | `columns` | `TableColumn[]` | `[]` | Colonnes du tableau associé. **Fourni → un menu déroulant « Colonnes » apparaît** (cases à cocher afficher/masquer). Voir §6 bis. |
36
+ | `storageKey` | `string` | — | Identifiant **stable** du tableau pour persister l'état en localStorage (ex. `'users/list'`). Sans clé : le menu fonctionne mais l'état n'est pas mémorisé. |
37
+ | `columnsLabel` | `string` | `_COMMON._TABLE.COLUMNS` | Clé i18n du libellé du bouton « Colonnes ». |
35
38
 
36
39
  ### Outputs
37
40
 
38
41
  | Output | Payload | Description |
39
42
  |--------|---------|-------------|
40
43
  | `action` | `PageHeaderActionEnum` | Émis au clic sur une action de la barre. Le bouton retour n'émet pas (géré en interne). |
44
+ | `columnsChange` | `TableColumn[]` | Émis quand la visibilité des colonnes change (colonnes avec `hidden` à jour). À renvoyer dans le `signal`/state lié à la `cw-table`. |
41
45
 
42
46
  ### Contenu projeté
43
47
 
@@ -134,6 +138,47 @@ onAction(action: PageHeaderActionEnum): void {
134
138
 
135
139
  ---
136
140
 
141
+ ## 4 bis. Menu « Colonnes » (visibilité + persistance)
142
+
143
+ Quand on passe `columns` au page-header, un bouton **Colonnes** apparaît : un dropdown de cases à cocher pour afficher/masquer chaque colonne du tableau associé. L'état (colonnes masquées) est **persisté en localStorage** par tableau.
144
+
145
+ ```ts
146
+ import { PageHeaderComponent, TableComponent, TableColumn } from '@cityway/bo-ui';
147
+
148
+ @Component({
149
+ standalone: true,
150
+ imports: [PageHeaderComponent, TableComponent],
151
+ template: `
152
+ <cw-page-header
153
+ [title]="'DOMAIN.USERS.TITLE'"
154
+ [columns]="columns()"
155
+ storageKey="users/list"
156
+ (columnsChange)="columns.set($event)">
157
+ </cw-page-header>
158
+
159
+ <cw-table [columns]="columns()" [data]="rows()"></cw-table>
160
+ `,
161
+ })
162
+ export class UsersPage {
163
+ // Source de vérité unique, liée au header (contrôle) ET à la table (rendu).
164
+ columns = signal<TableColumn[]>([
165
+ { key: 'name', label: 'DOMAIN.USERS.NAME' },
166
+ { key: 'email', label: 'DOMAIN.USERS.EMAIL' },
167
+ { key: 'createdAt', label: 'DOMAIN.USERS.CREATED', hidden: true }, // masquée par défaut
168
+ { key: 'actions', label: '', type: 'actions' }, // jamais masquable
169
+ ]);
170
+ }
171
+ ```
172
+
173
+ Règles :
174
+ - **Activation** : le menu n'apparaît que si `columns` contient au moins une colonne masquable. Sans `columns`, pas de menu.
175
+ - **Colonnes exclues** : `type='actions'` (jamais masquable) et toute colonne `hideable: false`.
176
+ - **Garde-fou** : impossible de masquer la **dernière** colonne masquable visible (sa case est désactivée).
177
+ - **Persistance** : une seule clé localStorage `cw-table-columns` → `{ [storageKey]: string[] }`, **on ne stocke que les clés des colonnes masquées**. Au chargement, l'état mémorisé prime sur les `hidden` du config ; **sans `storageKey`**, le menu fonctionne mais rien n'est mémorisé.
178
+ - **Helpers** : `loadHiddenColumns(storageKey)` / `saveHiddenColumns(storageKey, keys)` exportés par `@cityway/bo-ui` (le page-header les utilise en interne).
179
+
180
+ ---
181
+
137
182
  ## 5. Notes d'intégration
138
183
 
139
184
  - **i18n** : `title` et `description` passent par `translate` → fournir des **clés**, pas du texte en dur. `description` est rendue en `[innerHTML]` (peut contenir du HTML/markup traduit).
@@ -0,0 +1,140 @@
1
+ # `cw-progress-bar` — Progress bar
2
+
3
+ > Lib : `@cityway/bo-ui` · Sélecteur : `cw-progress-bar` · Standalone : oui
4
+ > Import : `import { ProgressBarComponent } from '@cityway/bo-ui';`
5
+
6
+ ---
7
+
8
+ ## 1. Rôle & quand l'utiliser
9
+
10
+ Barre de progression **déterministe** : visualise l'avancement d'une valeur connue sur une échelle (`value` / `max`), de 0 à 100 %.
11
+
12
+ Couvre :
13
+
14
+ - deux **tailles** : `md` (16px, libellé de pourcentage possible) et `sm` (8px, barre fine) ;
15
+ - quatre **types** de couleur issus du DS : `information` (défaut), `success`, `warning`, `danger` ;
16
+ - l'affichage optionnel du **pourcentage** dans la barre (`showValue`, taille `md` uniquement) ;
17
+ - une échelle **personnalisée** via `max` (ex. 320 / 500).
18
+
19
+ À ne PAS utiliser pour :
20
+
21
+ - un état de chargement **indéterminé** (durée inconnue) → utiliser `cw-loader` ;
22
+ - un curseur de saisie d'une valeur → utiliser `cw-form-field` (`type=slider` / `range`).
23
+
24
+ ---
25
+
26
+ ## 2. API
27
+
28
+ ### Inputs
29
+
30
+ | Input | Type | Défaut | Description |
31
+ |-------|------|--------|-------------|
32
+ | `value` | `number` | — (**requis**) | Valeur courante d'avancement. Bornée à `[0, max]` pour le calcul du pourcentage (`input.required`). |
33
+ | `max` | `number` | `100` | Valeur correspondant à 100 % de la barre. |
34
+ | `size` | `ProgressBarSizeEnum` | `md` | Hauteur de la barre (`md` = 16px / `sm` = 8px). |
35
+ | `type` | `ProgressBarTypeEnum` | `information` | Couleur de remplissage. |
36
+ | `showValue` | `boolean` | `false` | Affiche le pourcentage arrondi dans la barre. **Ignoré en taille `sm`** (le DS ne fournit pas de couleur de texte `on-*` en `sm`). |
37
+ | `label` | `string` | `undefined` | Libellé accessible (`aria-label`). À fournir si la barre n'est pas déjà décrite par un texte voisin. |
38
+ | `dataTest` | `string` | `undefined` | Pose l'attribut `data-test-ctw` pour le ciblage E2E. |
39
+
40
+ ### Outputs
41
+
42
+ Aucun. Le composant est purement présentiel (« controlled ») : il affiche la valeur qu'on lui passe.
43
+
44
+ ### Comportement de rendu
45
+
46
+ - Le pourcentage affiché et la largeur du remplissage valent `round(clamp(value / max) * 100)`, borné à `0..100`.
47
+ - `role="progressbar"` avec `aria-valuenow` (= `value`), `aria-valuemin="0"` et `aria-valuemax` (= `max`).
48
+ - Le host porte la classe `cw-progressbar` : les tokens DS `component/progressbar/*` y sont scopés (résolution dark-aware automatique).
49
+
50
+ ---
51
+
52
+ ## 3. Types
53
+
54
+ ```ts
55
+ enum ProgressBarSizeEnum {
56
+ md = 'md',
57
+ sm = 'sm',
58
+ }
59
+
60
+ enum ProgressBarTypeEnum {
61
+ information = 'information',
62
+ success = 'success',
63
+ warning = 'warning',
64
+ danger = 'danger',
65
+ }
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 4. Exemples
71
+
72
+ ### Barre simple
73
+
74
+ ```html
75
+ <cw-progress-bar [value]="60" label="Avancement de l'import"></cw-progress-bar>
76
+ ```
77
+
78
+ ### Avec pourcentage et type
79
+
80
+ ```html
81
+ <cw-progress-bar [value]="75" type="success" [showValue]="true"></cw-progress-bar>
82
+ ```
83
+
84
+ ### Échelle personnalisée
85
+
86
+ ```html
87
+ <!-- 320 / 500 = 64 % -->
88
+ <cw-progress-bar [value]="320" [max]="500" [showValue]="true" label="320 sur 500"></cw-progress-bar>
89
+ ```
90
+
91
+ ### Liaison à un signal
92
+
93
+ ```ts
94
+ import { ProgressBarComponent, ProgressBarTypeEnum } from '@cityway/bo-ui';
95
+
96
+ @Component({
97
+ selector: 'app-import',
98
+ standalone: true,
99
+ imports: [ProgressBarComponent],
100
+ template: `
101
+ <cw-progress-bar
102
+ [value]="progress()"
103
+ [type]="progressType"
104
+ [showValue]="true"
105
+ label="Progression de l'import">
106
+ </cw-progress-bar>
107
+ `,
108
+ })
109
+ export class ImportComponent {
110
+ progress = signal(0);
111
+ readonly progressType = ProgressBarTypeEnum.information;
112
+ }
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 5. Notes d'intégration
118
+
119
+ - **Composant déterministe** : à réserver aux avancements dont la valeur est connue. Pour un chargement de durée inconnue, préférer `cw-loader`.
120
+ - **`showValue` + `sm`** : le libellé inline n'est rendu qu'en taille `md`. Une barre `sm` reste muette même si `showValue` est à `true`.
121
+ - **Accessibilité** : fournir `label` quand aucun texte visible adjacent ne décrit la barre, sinon le lecteur d'écran annonce une progression sans contexte.
122
+ - **Dark mode** : aucune action requise. Les couleurs (`information`/`success`/`warning`/`danger`, piste `neutral`, texte `on-*`) proviennent des tokens DS scopés sur `.cw-progressbar` et basculent automatiquement en thème sombre.
123
+ - **En cellule de tableau** : le DS prévoit un usage `Table / Column / Progressbar` (barre `sm`). Insérer le `cw-progress-bar` directement dans le template de cellule de `cw-table`.
124
+
125
+ ---
126
+
127
+ ## 6. Prompts-types (génération assistée)
128
+
129
+ > Exemples de formulation pour demander à Claude de générer du code consommant ce composant.
130
+
131
+ - « Ajoute une `cw-progress-bar` `success` avec le pourcentage affiché, pilotée par un signal `progress`. »
132
+ - « Mets une barre de progression fine (`sm`) de type `information` dans la colonne "Avancement" de ma `cw-table`. »
133
+ - « Affiche une progression 320/500 avec `max` et le pourcentage dans la barre. »
134
+
135
+ **Rappels pour Claude :**
136
+ - Importer `ProgressBarComponent` (standalone) dans les `imports` du composant hôte.
137
+ - `value` est **requis** (`input.required`).
138
+ - `showValue` n'a d'effet qu'en taille `md`.
139
+ - Toujours fournir un `label` accessible si la barre n'a pas de texte descriptif adjacent.
140
+ - Pour un chargement indéterminé, utiliser `cw-loader` et non ce composant.
@@ -36,6 +36,9 @@ Dépend de `@cityway/basic-ui` (badge, button, icon, image, loader, modale de su
36
36
  | `pagination` | `Pagination` | `undefined` | Config de pagination (intègre `cw-pagination`). |
37
37
  | `bulkActions` | `BulkAction[]` | `[]` | Actions groupées (nécessite `checkbox`). |
38
38
  | `rowActions` | `RowActionsConfig` | `undefined` | Actions par ligne (API déclarative). |
39
+ | `emptyStateNoData` | `TableEmptyStateConfig` | `undefined` | État vide quand `data` est vide **et** table non filtrée (`cw-empty-state`). |
40
+ | `emptyStateNoResult` | `TableEmptyStateConfig` | `undefined` | État vide quand un filtrage ne renvoie rien (`isFiltered=true`). |
41
+ | `isFiltered` | `boolean` | `false` | Des filtres sont actifs → pilote le choix noData vs noResult. |
39
42
 
40
43
  ### Outputs
41
44
 
@@ -74,6 +77,8 @@ interface TableColumn {
74
77
  defaultSort?: 'asc' | 'desc'; // tri initial
75
78
  hidden?: boolean;
76
79
  clickable?: boolean; // rend la cellule cliquable (-> cellClick)
80
+ translate?: boolean; // traduit la VALEUR (text/link). Défaut false. Voir ci-dessous.
81
+ hideable?: boolean; // proposée au masquage dans le menu « Colonnes ». Défaut true.
77
82
  }
78
83
 
79
84
  interface BadgeConfig {
@@ -189,6 +194,9 @@ rowActions: RowActionsConfig = {
189
194
  ## 5. Notes d'intégration
190
195
 
191
196
  - **i18n** : tous les `label` (colonnes, actions) sont des **clés** traduites en interne.
197
+ - **Visibilité des colonnes** : le menu « Colonnes » (afficher/masquer + persistance localStorage) est porté par **`cw-page-header`** (lui passer `[columns]` + `storageKey`, relier `(columnsChange)`). La `cw-table` ne fait que rendre les colonnes non `hidden` ; côté colonne, `hideable: false` exclut du menu et `type='actions'` est exclu d'office. Voir la doc `cw-page-header` §4 bis.
198
+ - **État vide** : fournir `emptyStateNoData` et/ou `emptyStateNoResult` (+ `isFiltered`) pour afficher un `cw-empty-state` (illustration + titre + description + 2 boutons avec `click`). Sans config, la table garde le texte `NO_RESULT`. Voir la doc `cw-empty-state`.
199
+ - **Traduction des VALEURS de cellule** : les colonnes `text` / `link` affichent la donnée **brute par défaut**. Mettre `translate: true` **uniquement** quand la valeur est elle-même une clé i18n (enum / statut affiché en texte). Sinon une donnée qui coïncide avec une clé serait traduite à tort — typiquement un code applicatif `"NEWS"` rendu en `[object Object]` car la clé pointe sur une branche d'objet. (Les `badge` traduisent déjà leur `label` ; les en-têtes `label` sont toujours traduits.)
192
200
  - **OnPush** : `data`/`columns` sont des signals → fournir des références à jour (set/update du signal).
193
201
  - **`rowActions` vs `#actionsTemplate`** : ne fournir qu'un seul. `rowActions` est l'API recommandée ; le template custom reste pour les cas hors standard.
194
202
  - **Suppression** : `type='delete'` ouvre la modale de confirmation de `basic-ui` ; n'émet `bulkDelete`/`bulkAction` qu'après confirmation.