@cityway/bo-ui 1.1.0-beta011 → 1.1.0-beta014
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/cityway-bo-ui-1.1.0-beta014.tgz +0 -0
- package/docs/components/drag-n-drop-nested-list.md +14 -8
- package/fesm2022/cityway-bo-ui.mjs +86 -10
- package/fesm2022/cityway-bo-ui.mjs.map +1 -1
- package/index.d.ts +37 -5
- package/package.json +2 -2
- package/styles/bo-ui.styles.min.css +1 -1
- package/styles/bo-ui.styles.min.css.map +1 -1
- package/cityway-bo-ui-1.1.0-beta011.tgz +0 -0
|
Binary file
|
|
@@ -29,11 +29,11 @@ Liste hiérarchique réordonnable par glisser-déposer (CDK drag-drop), pilotée
|
|
|
29
29
|
| Input | Type | Défaut | Description |
|
|
30
30
|
|-------|------|--------|-------------|
|
|
31
31
|
| `items` | `DragItem[]` | `[]` | Arbre des items à afficher. Le composant en fait une **copie interne mutable** sur laquelle le CDK opère. Voir §3. |
|
|
32
|
-
| `itemTemplate` | `TemplateRef<any> \| undefined` | `undefined` | Template du **corps** de carte (slot). Reçoit `$implicit = item` et `depth`. Si absent,
|
|
32
|
+
| `itemTemplate` | `TemplateRef<any> \| undefined` | `undefined` | Template du **corps** de carte (slot). Reçoit `$implicit = item` et `depth`. Si absent, **aucun corps n'est rendu** — sauf `item.code`, affiché seul (le titre de l'en-tête porte déjà `title ?? label`). |
|
|
33
33
|
| `column` | `DragListColumn \| undefined` | `undefined` | Configuration de la colonne : titre, défauts de visibilité des actions, libellés, plafonds. Voir §3. |
|
|
34
34
|
| `reorderOnDrop` | `boolean` | `true` | Renumérote `order` (1..n par niveau) récursivement à chaque drop. `false` = déplacement visuel seul, `order` intact. |
|
|
35
35
|
| `maxDepth` | `number \| undefined` | `undefined` | Profondeur max (0-based, racine = 0). Une carte à `depth < maxDepth` peut recevoir des enfants ; `>= maxDepth` est terminale. `undefined` = imbrication infinie. Ex. `maxDepth = 1` → 2 niveaux. |
|
|
36
|
-
| `selectedId` | `number \| string \| undefined` | `undefined` | Sélection **exclusive** gérée par la lib : la carte dont `id === selectedId` reçoit la classe `ddn-list-card-selected
|
|
36
|
+
| `selectedId` | `number \| string \| undefined` | `undefined` | Sélection **exclusive** gérée par la lib : la carte dont `id === selectedId` reçoit la classe `ddn-list-card-selected` — **elle seule**, jamais ses parents (voir §5, « Rendu de la sélection en profondeur »). Le flag `DragItem.selected` reste supporté en parallèle. ⚠️ Les `id` doivent être uniques **sur tout l'arbre**, pas seulement par niveau. |
|
|
37
37
|
|
|
38
38
|
### Outputs
|
|
39
39
|
|
|
@@ -60,6 +60,8 @@ Le **corps** de chaque carte est fourni par un `TemplateRef` passé à `[itemTem
|
|
|
60
60
|
|
|
61
61
|
> L'en-tête (titre, sous-titre, badge, compteur, actions, poignée) reste **toujours** data-driven ; seul le corps est personnalisable.
|
|
62
62
|
|
|
63
|
+
Sans `[itemTemplate]`, la carte se réduit à son en-tête : le composant ne réaffiche pas le label, qui est déjà le titre. Seul `item.code`, s'il est renseigné, est rendu dans le corps. C'est le mode à privilégier quand l'en-tête suffit — chaque corps redondant coûte une hauteur de carte à tous les niveaux de l'arbre.
|
|
64
|
+
|
|
63
65
|
---
|
|
64
66
|
|
|
65
67
|
## 3. Modèles & types
|
|
@@ -67,8 +69,8 @@ Le **corps** de chaque carte est fourni par un `TemplateRef` passé à `[itemTem
|
|
|
67
69
|
```ts
|
|
68
70
|
interface DragItem {
|
|
69
71
|
id: number | string; // clé de tri (trackBy) — unique
|
|
70
|
-
label: string; // libellé (fallback de title
|
|
71
|
-
code?: string; // affiché dans le corps
|
|
72
|
+
label: string; // libellé (fallback de title dans l'en-tête)
|
|
73
|
+
code?: string; // affiché seul dans le corps quand il n'y a pas d'itemTemplate
|
|
72
74
|
order?: number; // position 1..n (renumérotée si reorderOnDrop)
|
|
73
75
|
disabled?: boolean; // verrouille le drag de CETTE carte (poignée inactive)
|
|
74
76
|
children?: DragItem[]; // sous-arbre
|
|
@@ -101,8 +103,8 @@ interface DragItemActions { // chaque champ = visibilité (booléen). unde
|
|
|
101
103
|
|
|
102
104
|
interface DragListColumn {
|
|
103
105
|
title: string; // titre de colonne (clé i18n) — affiché « Titre (count) » / « (count/max) »
|
|
104
|
-
description?: string;
|
|
105
|
-
descriptionRwd?: string;
|
|
106
|
+
description?: string; // IGNORÉ par ce composant (n'existe que pour cw-drag-n-drop-list)
|
|
107
|
+
descriptionRwd?: string; // idem
|
|
106
108
|
cssClass?: string; // classe sur chaque <ul> de niveau
|
|
107
109
|
|
|
108
110
|
collapsible?: boolean; // cartes pliables (défaut true) ; false désactive globalement
|
|
@@ -256,6 +258,10 @@ restore(t: DragItem) {
|
|
|
256
258
|
onReorder(items: DragItem[]) { this.items = items; }
|
|
257
259
|
```
|
|
258
260
|
|
|
261
|
+
**Rendu en profondeur.** Une seule carte est peinte à l'écran, jamais toute une branche. La carte sélectionnée porte `ddn-list-card-selected` ; un parent qui la contient ne porte `ddn-list-card-has-selection` que **s'il est replié** — la carte sélectionnée n'étant alors pas rendue (`destroyOnHide` de `cw-card`), le parent en reprend le rendu et signale « un élément actif est là-dedans ». Déplié, il redevient neutre. La lib suit le pliage réel de chaque carte via `(collapseClicked)`, pas seulement l'état initial.
|
|
262
|
+
|
|
263
|
+
⚠️ **Unicité des `id`.** La correspondance se fait sur `id === selectedId` à tous les niveaux. Si un item de niveau 1 et un item de niveau 2 partagent le même `id` (typique quand chaque niveau vient d'une table différente : thème `1`, fichier `1`), **les deux cartes s'allument**. Préfixer côté hôte (`` `theme-${t.id}` ``, `` `file-${f.id}` ``) ou utiliser une clé composite.
|
|
264
|
+
|
|
259
265
|
### Corps de carte custom (`itemTemplate`)
|
|
260
266
|
|
|
261
267
|
```html
|
|
@@ -272,12 +278,12 @@ onReorder(items: DragItem[]) { this.items = items; }
|
|
|
272
278
|
|
|
273
279
|
## 5. Notes d'intégration
|
|
274
280
|
|
|
275
|
-
- **CDK drag-drop** : repose sur `@angular/cdk/drag-drop` (`DragDropModule`). Chaque niveau est un `cdkDropList` **isolé** (pas de `cdkDropListConnectedTo`) → le tri est **intra-liste à chaque niveau**, jamais entre niveaux ni entre listes. Le drag ne démarre que depuis la **poignée** (`cdkDragHandle`).
|
|
281
|
+
- **CDK drag-drop** : repose sur `@angular/cdk/drag-drop` (`DragDropModule`). Chaque niveau est un `cdkDropList` **isolé** (pas de `cdkDropListConnectedTo`) → le tri est **intra-liste à chaque niveau**, jamais entre niveaux ni entre listes. Le drag ne démarre que depuis la **poignée** (`cdkDragHandle`). Poignée inactive (carte `disabled` ou `pendingDelete`) : elle garde son rendu normal, seule l'interaction disparaît — le rendu `disabled` du `.btn` (aplat plein `base-disabled`) est neutralisé sur `.ddn-list-handle`, sinon une poignée morte est plus voyante qu'une poignée active.
|
|
276
282
|
- **Source de vérité** : le composant clone `items` dans une copie interne mutable (`_items`) à chaque changement (effect). C'est cette copie que le CDK déplace ; l'arbre réordonné est émis via `itemsChange`. **Persister** ce payload côté hôte (sinon un re-rendu ultérieur repart de l'ordre périmé).
|
|
277
283
|
- **Imbrication & `maxDepth`** : `maxDepth` est 0-based (racine = 0). `maxDepth = 1` ⇒ 2 niveaux. `undefined` ⇒ imbrication infinie (ajout possible partout).
|
|
278
284
|
- **Type de carte alterné** : la lib alterne `CardTypeEnum.default` (profondeur paire) / `light` (impaire).
|
|
279
285
|
- **i18n** : tous les libellés (`column.title`, `addLabel`, `maxReachedLabel`, `restoreBlockedLabel`, libellés de badge…) passent par `translate` → fournir des **clés**, pas du texte en dur.
|
|
280
|
-
- **États & styles** : la lib **lit** `selected` / `selectedId` / `pendingDelete` et pose les classes DS (`ddn-list-card-selected`, `ddn-list-card-deleting`) ; elle ne mute pas les flags. C'est l'hôte qui les flippe et re-passe `items`. Préférer `selectedId` (exclusif, sans parcours d'arbre) au flag `selected` (multi-sélection non garantie).
|
|
286
|
+
- **États & styles** : la lib **lit** `selected` / `selectedId` / `pendingDelete` et pose les classes DS (`ddn-list-card-selected`, `ddn-list-card-has-selection`, `ddn-list-card-deleting`) ; elle ne mute pas les flags. C'est l'hôte qui les flippe et re-passe `items`. Préférer `selectedId` (exclusif, sans parcours d'arbre) au flag `selected` (multi-sélection non garantie).
|
|
281
287
|
- **Soft-delete** : sur une carte `pendingDelete`, le corps est masqué (carte compacte, non pliable, non déplaçable) et la corbeille devient « Restaurer » (émet `restore`, pas `delete`). En mode `excludePendingDeleteFromMax`, restaurer peut être **bloqué** si le niveau est entre-temps redevenu plein.
|
|
282
288
|
|
|
283
289
|
---
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, ChangeDetectionStrategy, Component, output, effect, computed, inject, contentChild,
|
|
2
|
+
import { input, ChangeDetectionStrategy, Component, output, effect, signal, computed, isDevMode, inject, contentChild, isSignal, DestroyRef, viewChildren, viewChild, afterRenderEffect, afterNextRender, contentChildren } from '@angular/core';
|
|
3
3
|
import * as i1 from '@ngx-translate/core';
|
|
4
4
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
5
5
|
import * as i1$3 from '@angular/common';
|
|
@@ -175,9 +175,14 @@ class DragNDropNestedListComponent {
|
|
|
175
175
|
this.maxDepth = input(undefined, ...(ngDevMode ? [{ debugName: "maxDepth" }] : []));
|
|
176
176
|
/**
|
|
177
177
|
* Sélection EXCLUSIVE gérée par la lib : la carte dont l'`id` vaut `selectedId` reçoit
|
|
178
|
-
* la classe `ddn-list-card-selected
|
|
179
|
-
*
|
|
178
|
+
* la classe `ddn-list-card-selected` — elle seule ; un parent n'est jamais repeint, il est
|
|
179
|
+
* seulement marqué d'un liseré quand il est replié (cf. `cardCssClass`).
|
|
180
|
+
* Sans avoir à manipuler `DragItem.selected` (qui reste supporté en parallèle).
|
|
180
181
|
* Piloté par le consommateur (ex. l'id de la carte en cours d'édition ; `undefined` = aucune).
|
|
182
|
+
*
|
|
183
|
+
* ⚠️ La correspondance est un `===` sur l'`id` à TOUS les niveaux : les `id` doivent être
|
|
184
|
+
* uniques sur l'arbre entier, pas seulement au sein d'un niveau. Deux items de niveaux
|
|
185
|
+
* différents qui partagent un `id` (thème `1` / fichier `1`) s'allument tous les deux.
|
|
181
186
|
*/
|
|
182
187
|
this.selectedId = input(undefined, ...(ngDevMode ? [{ debugName: "selectedId" }] : []));
|
|
183
188
|
this.itemsChange = output();
|
|
@@ -195,9 +200,57 @@ class DragNDropNestedListComponent {
|
|
|
195
200
|
this.alertType = AlertTypeEnum;
|
|
196
201
|
// Copie interne mutable sur laquelle le CDK opère (pas un signal — cf. DragNDropListComponent)
|
|
197
202
|
this._items = [];
|
|
203
|
+
/**
|
|
204
|
+
* État de pliage par carte, alimenté par `(collapseClicked)` de `cw-card`.
|
|
205
|
+
* Une carte absente de la map n'a jamais été manipulée : son état est celui posé à l'init
|
|
206
|
+
* (`isCollapsible`, cf. `isCollapsedCard`). Sert au marquage « sélection repliée » des ancêtres.
|
|
207
|
+
*/
|
|
208
|
+
this.collapsedById = signal(new Map(), ...(ngDevMode ? [{ debugName: "collapsedById" }] : []));
|
|
209
|
+
/**
|
|
210
|
+
* Ids des ancêtres de la carte sélectionnée (parent, grand-parent, …).
|
|
211
|
+
* Calculé sur `items()` : l'imbrication ne change jamais au drag (chaque niveau est une
|
|
212
|
+
* `cdkDropList` isolée), seul l'ordre intra-niveau bouge.
|
|
213
|
+
*/
|
|
214
|
+
this.selectedAncestorIds = computed(() => {
|
|
215
|
+
const selectedId = this.selectedId();
|
|
216
|
+
const ancestors = new Set();
|
|
217
|
+
const walk = (nodes, trail) => {
|
|
218
|
+
for (const node of nodes) {
|
|
219
|
+
if (node.selected || (selectedId !== undefined && node.id === selectedId)) {
|
|
220
|
+
trail.forEach(id => ancestors.add(id));
|
|
221
|
+
}
|
|
222
|
+
if (node.children?.length)
|
|
223
|
+
walk(node.children, [...trail, node.id]);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
walk(this.items(), []);
|
|
227
|
+
return ancestors;
|
|
228
|
+
}, ...(ngDevMode ? [{ debugName: "selectedAncestorIds" }] : []));
|
|
198
229
|
effect(() => {
|
|
199
230
|
this._items = this.cloneTree(this.items());
|
|
200
231
|
});
|
|
232
|
+
// Diagnostic dev : `selectedId` doit désigner UNE carte. Des `id` qui se répètent d'un
|
|
233
|
+
// niveau à l'autre (thème `1` / fichier `1`, typique quand chaque niveau vient d'une table
|
|
234
|
+
// différente) en allument plusieurs — symptôme : « toute la branche est en surbrillance ».
|
|
235
|
+
effect(() => {
|
|
236
|
+
const selectedId = this.selectedId();
|
|
237
|
+
if (!isDevMode() || selectedId === undefined)
|
|
238
|
+
return;
|
|
239
|
+
let matches = 0;
|
|
240
|
+
const count = (nodes) => {
|
|
241
|
+
for (const node of nodes) {
|
|
242
|
+
if (node.id === selectedId)
|
|
243
|
+
matches++;
|
|
244
|
+
if (node.children?.length)
|
|
245
|
+
count(node.children);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
count(this.items());
|
|
249
|
+
if (matches > 1) {
|
|
250
|
+
console.warn(`[cw-drag-n-drop-nested-list] selectedId="${selectedId}" correspond à ${matches} cartes : `
|
|
251
|
+
+ `les \`id\` doivent être uniques sur tout l'arbre, pas seulement au sein d'un niveau.`);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
201
254
|
}
|
|
202
255
|
drop(event) {
|
|
203
256
|
// Pas de transferArrayItem : chaque cdkDropList est isolée (pas de connectedTo),
|
|
@@ -289,18 +342,41 @@ class DragNDropNestedListComponent {
|
|
|
289
342
|
}
|
|
290
343
|
/**
|
|
291
344
|
* Classe(s) de la carte selon son état (posées par la lib, stylées dans le SCSS DS).
|
|
292
|
-
*
|
|
293
|
-
*
|
|
345
|
+
* - `ddn-list-card-selected` : la carte sélectionnée elle-même (`item.id === selectedId`,
|
|
346
|
+
* ou flag legacy `item.selected`). **Elle seule** — le fond de sélection ne remonte pas
|
|
347
|
+
* sur les ancêtres, sinon toute la branche prend la même couleur et plus rien ne se lit.
|
|
348
|
+
* - `ddn-list-card-has-selection` : ancêtre **replié** de la carte sélectionnée, qui reprend
|
|
349
|
+
* le rendu de sélection — la carte sélectionnée n'étant pas rendue tant que le parent est
|
|
350
|
+
* replié (`destroyOnHide` de `cw-card`), une seule carte est peinte à l'écran. Dépliée,
|
|
351
|
+
* la classe n'est plus posée : la sélection se voit d'elle-même sur la bonne carte.
|
|
352
|
+
* - `ddn-list-card-deleting` : carte `pendingDelete`.
|
|
294
353
|
*/
|
|
295
|
-
cardCssClass(item) {
|
|
354
|
+
cardCssClass(item, depth) {
|
|
296
355
|
const selectedId = this.selectedId();
|
|
297
356
|
const selected = item.selected || (selectedId !== undefined && item.id === selectedId);
|
|
357
|
+
const hidesSelection = !selected
|
|
358
|
+
&& this.selectedAncestorIds().has(item.id)
|
|
359
|
+
&& this.isCollapsedCard(item, depth);
|
|
298
360
|
return [
|
|
299
361
|
'ddn-list-card',
|
|
300
362
|
selected ? 'ddn-list-card-selected' : '',
|
|
363
|
+
hidesSelection ? 'ddn-list-card-has-selection' : '',
|
|
301
364
|
item.pendingDelete ? 'ddn-list-card-deleting' : '',
|
|
302
365
|
].filter(Boolean).join(' ');
|
|
303
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Carte repliée ? Réponse de la map alimentée par `(collapseClicked)`, sinon état initial
|
|
369
|
+
* (une carte pliable démarre repliée). Sert aussi de `[collapsed]` : l'état survit ainsi
|
|
370
|
+
* à un re-rendu de la liste (drop, mise à jour de `items`).
|
|
371
|
+
*/
|
|
372
|
+
isCollapsedCard(item, depth) {
|
|
373
|
+
return this.collapsedById().get(item.id) ?? this.isCollapsible(item, depth);
|
|
374
|
+
}
|
|
375
|
+
onCollapseChange(item, collapsed) {
|
|
376
|
+
const next = new Map(this.collapsedById());
|
|
377
|
+
next.set(item.id, collapsed);
|
|
378
|
+
this.collapsedById.set(next);
|
|
379
|
+
}
|
|
304
380
|
/**
|
|
305
381
|
* Libellé du compteur d'enfants, en gérant singulier/pluriel.
|
|
306
382
|
* Affiché aussi à `0` quand la carte est vide mais peut recevoir des enfants
|
|
@@ -341,11 +417,11 @@ class DragNDropNestedListComponent {
|
|
|
341
417
|
}));
|
|
342
418
|
}
|
|
343
419
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: DragNDropNestedListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
344
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.20", type: DragNDropNestedListComponent, isStandalone: true, selector: "cw-drag-n-drop-nested-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: false, transformFunction: null }, reorderOnDrop: { classPropertyName: "reorderOnDrop", publicName: "reorderOnDrop", isSignal: true, isRequired: false, transformFunction: null }, maxDepth: { classPropertyName: "maxDepth", publicName: "maxDepth", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemsChange: "itemsChange", view: "view", edit: "edit", delete: "delete", restore: "restore", add: "add" }, ngImport: i0, template: "<div class=\"ddn-list d-flex-v gap-md\">\n <div class=\"d-flex-h justify-between\">\n @if (column()?.title) {\n <h2>{{ column()!.title | translate }} ({{ columnCountLabel() }})</h2>\n }\n\n @if (column()?.showAddRoot) {\n <cw-button cssClass=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addRootLabel ?? column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(_items, 0)\" (btnAction)=\"onAdd(undefined, 0)\" />\n }\n </div>\n\n <ng-container *ngTemplateOutlet=\"nodeTpl; context: { $implicit: _items, depth: 0, parent: undefined }\" />\n</div>\n\n<!--\n Template r\u00E9cursif : \u00E0 chaque niveau, on rend un cdkDropList isol\u00E9\n (pas de cdkDropListConnectedTo => transfert inter-listes impossible),\n puis on r\u00E9-instancie le m\u00EAme template pour la sous-liste de chaque enfant.\n-->\n<ng-template #nodeTpl let-nodes let-depth=\"depth\" let-parent=\"parent\">\n @if (isLevelFull(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-max-alert\">\n {{ (column()?.maxReachedLabel ?? '_COMMON.MAX_ITEMS_REACHED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <ul class=\"list-unstyled d-flex-v gap-md ms-none\" [ngClass]=\"column()?.cssClass\" [attr.data-depth]=\"depth\"\n cdkDropList [cdkDropListData]=\"nodes\" (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of nodes; track item.id) {\n <li cdkDrag [cdkDragDisabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" cdkDragPreviewClass=\"ddn-list-card-preview\">\n <cw-card [cssClass]=\"cardCssClass(item)\" [title]=\"(item.title ?? item.label) || ''\"\n [subtitle]=\"item.subtitle ?? ''\" [type]=\"cardType(depth)\" [collapsible]=\"isCollapsible(item, depth)\"\n [collapsed]=\"isCollapsible(item, depth)\" [collapseStretched]=\"false\">\n\n <!-- Poign\u00E9e de drag (\u00E0 gauche du titre) : le glisser ne d\u00E9marre que d'ici -->\n <button header-start type=\"button\" class=\"ddn-list-handle\" cdkDragHandle\n [disabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" [attr.aria-label]=\"'_COMMON._ACTION.MOVE' | translate\">\n <cw-icon [icon]=\"spriteIcon.grip\" [iconSize]=\"iconSize['md']\" />\n </button>\n\n <!-- En-t\u00EAte : compteur d'enfants + badge + actions -->\n <div header-custom-area class=\"d-flex-h gap-2xs justify-end align-start\">\n @if (childrenCountLabel(item, depth); as count) {\n <span class=\"ddn-list-count fs fs-xs\">{{ count }}</span>\n }\n\n @if (item.badge) {\n <cw-badge [type]=\"item.badge.type\" [label]=\"item.badge.label\" [withIcon]=\"item.badge.icon\" />\n }\n\n <!-- Sur une carte pendingDelete, seul \u00AB Restaurer \u00BB est propos\u00E9 (view/edit masqu\u00E9s). -->\n @if (!item.pendingDelete && showAction(item, 'view')) {\n <cw-button label=\"_COMMON._ACTION.VIEW\" [withIcon]=\"spriteIcon.search\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"view.emit(item)\" />\n }\n @if (!item.pendingDelete && showAction(item, 'edit')) {\n <cw-button label=\"_COMMON._ACTION.EDIT\" [withIcon]=\"spriteIcon.edit\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"edit.emit(item)\" />\n }\n @if (showAction(item, 'delete')) {\n @if (item.pendingDelete) {\n <!-- Soft-delete : la corbeille bascule en \u00AB Restaurer \u00BB (d\u00E9sactiv\u00E9 si le niveau est plein). -->\n <cw-button label=\"_COMMON._ACTION.RESTORE\" [withIcon]=\"spriteIcon.toolbarRefresh\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-restore\"\n [isDisabled]=\"isRestoreBlocked(nodes, depth)\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"restore.emit(item)\" />\n } @else {\n <cw-button label=\"_COMMON._ACTION.DELETE\" [withIcon]=\"spriteIcon.trash\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-delete\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"delete.emit(item)\" />\n }\n }\n </div>\n\n <!-- Restauration impossible : niveau plein (mode excludePendingDeleteFromMax). -->\n @if (item.pendingDelete && isRestoreBlocked(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-restore-blocked-alert\">\n {{ (column()?.restoreBlockedLabel ?? '_COMMON.MAX_RESTORE_BLOCKED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <!-- Corps masqu\u00E9 sur une carte pendingDelete : on n'affiche que l'en-t\u00EAte (carte compacte,\n non pliable, non d\u00E9pla\u00E7able). L'encart \u00AB restauration impossible \u00BB ci-dessus reste, lui, visible. -->\n @if (!item.pendingDelete) {\n <!-- Corps : template custom (slot) ou fallback -->\n <ng-container\n *ngTemplateOutlet=\"itemTemplate() || defaultTemplate; context: { $implicit: item, depth: depth }\" />\n\n @if (item.children?.length) {\n <ng-container\n *ngTemplateOutlet=\"nodeTpl; context: { $implicit: item.children, depth: depth + 1, parent: item }\" />\n }\n\n @if (canAdd(item, depth)) {\n <div class=\"d-flex-h justify-end\">\n <cw-button class=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(item.children ?? [], depth + 1)\" (btnAction)=\"onAdd(item, depth + 1)\" />\n </div>\n }\n }\n </cw-card>\n </li>\n }\n\n </ul>\n</ng-template>\n\n<ng-template #defaultTemplate let-item>\n <div class=\"default-item d-flex justify-content-between\">\n <span>\n {{ item.label }}\n @if (item.code) { <span class=\"text-muted\">({{ item.code }})</span> }\n </span>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$1.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CardComponent, selector: "cw-card", inputs: ["title", "subtitle", "type", "titleRank", "cssClass", "collapsible", "collapsed", "disabled", "collapseLocked", "collapseStretched", "collapseId", "destroyOnHide"], outputs: ["collapsibleChange", "destroyOnHideChange", "collapseClicked"] }, { kind: "component", type: BadgeComponent, selector: "cw-badge", inputs: ["type", "label", "withIcon", "iconPosition", "cssClass", "skeletonMode", "dataTest"] }, { kind: "component", type: IconComponent, selector: "cw-icon", inputs: ["icon", "label", "type", "iconSize", "iconCssClass", "iconUiType", "iconColorCustom", "spritePath"] }, { kind: "component", type: ButtonComponent, selector: "cw-button", inputs: ["type", "label", "id", "link", "isDropdown", "hideCaret", "withIcon", "withOnlyIcon", "iconSize", "iconPosition", "dropdownPosition", "isMinWidth", "isDisabled", "isLoading", "loadingAnnounce", "cssClass", "dataTest", "skeletonMode", "withTooltip", "tooltipText", "tooltipTitle", "tooltipTrigger", "tooltipPosition", "tooltipType"], outputs: ["btnAction", "dropDownClicked"] }, { kind: "component", type: AlertComponent, selector: "cw-alert", inputs: ["type", "title", "isDismissible", "cssClass", "dataTest"], outputs: ["close"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
420
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.20", type: DragNDropNestedListComponent, isStandalone: true, selector: "cw-drag-n-drop-nested-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: false, transformFunction: null }, reorderOnDrop: { classPropertyName: "reorderOnDrop", publicName: "reorderOnDrop", isSignal: true, isRequired: false, transformFunction: null }, maxDepth: { classPropertyName: "maxDepth", publicName: "maxDepth", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemsChange: "itemsChange", view: "view", edit: "edit", delete: "delete", restore: "restore", add: "add" }, ngImport: i0, template: "<div class=\"ddn-list d-flex-v gap-md\">\n <div class=\"d-flex-h justify-between\">\n @if (column()?.title) {\n <h2>{{ column()!.title | translate }} ({{ columnCountLabel() }})</h2>\n }\n\n @if (column()?.showAddRoot) {\n <cw-button cssClass=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addRootLabel ?? column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(_items, 0)\" (btnAction)=\"onAdd(undefined, 0)\" />\n }\n </div>\n\n <ng-container *ngTemplateOutlet=\"nodeTpl; context: { $implicit: _items, depth: 0, parent: undefined }\" />\n</div>\n\n<!--\n Template r\u00E9cursif : \u00E0 chaque niveau, on rend un cdkDropList isol\u00E9\n (pas de cdkDropListConnectedTo => transfert inter-listes impossible),\n puis on r\u00E9-instancie le m\u00EAme template pour la sous-liste de chaque enfant.\n-->\n<ng-template #nodeTpl let-nodes let-depth=\"depth\" let-parent=\"parent\">\n @if (isLevelFull(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-max-alert\">\n {{ (column()?.maxReachedLabel ?? '_COMMON.MAX_ITEMS_REACHED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <ul class=\"list-unstyled d-flex-v gap-md ms-none\" [ngClass]=\"column()?.cssClass\" [attr.data-depth]=\"depth\"\n cdkDropList [cdkDropListData]=\"nodes\" (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of nodes; track item.id) {\n <li cdkDrag [cdkDragDisabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" cdkDragPreviewClass=\"ddn-list-card-preview\">\n <cw-card [cssClass]=\"cardCssClass(item, depth)\" [title]=\"(item.title ?? item.label) || ''\"\n [subtitle]=\"item.subtitle ?? ''\" [type]=\"cardType(depth)\" [collapsible]=\"isCollapsible(item, depth)\"\n [collapsed]=\"isCollapsedCard(item, depth)\" [collapseStretched]=\"false\"\n (collapseClicked)=\"onCollapseChange(item, $event)\">\n\n <!-- Poign\u00E9e de drag (\u00E0 gauche du titre) : le glisser ne d\u00E9marre que d'ici -->\n <button header-start type=\"button\" class=\"ddn-list-handle btn btn-ghost\" cdkDragHandle\n [disabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" [attr.aria-label]=\"'_COMMON._ACTION.MOVE' | translate\">\n <cw-icon [icon]=\"spriteIcon.grip\" [iconSize]=\"iconSize['md']\" />\n </button>\n\n <!-- En-t\u00EAte : compteur d'enfants + badge + actions -->\n <div header-custom-area class=\"d-flex-h gap-2xs justify-end align-start\">\n @if (childrenCountLabel(item, depth); as count) {\n <span class=\"ddn-list-count fs fs-xs\">{{ count }}</span>\n }\n\n @if (item.badge) {\n <cw-badge [type]=\"item.badge.type\" [label]=\"item.badge.label\" [withIcon]=\"item.badge.icon\" />\n }\n\n <!-- Sur une carte pendingDelete, seul \u00AB Restaurer \u00BB est propos\u00E9 (view/edit masqu\u00E9s). -->\n @if (!item.pendingDelete && showAction(item, 'view')) {\n <cw-button label=\"_COMMON._ACTION.VIEW\" [withIcon]=\"spriteIcon.search\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"view.emit(item)\" />\n }\n @if (!item.pendingDelete && showAction(item, 'edit')) {\n <cw-button label=\"_COMMON._ACTION.EDIT\" [withIcon]=\"spriteIcon.edit\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"edit.emit(item)\" />\n }\n @if (showAction(item, 'delete')) {\n @if (item.pendingDelete) {\n <!-- Soft-delete : la corbeille bascule en \u00AB Restaurer \u00BB (d\u00E9sactiv\u00E9 si le niveau est plein). -->\n <cw-button label=\"_COMMON._ACTION.RESTORE\" [withIcon]=\"spriteIcon.toolbarRefresh\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-restore\"\n [isDisabled]=\"isRestoreBlocked(nodes, depth)\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"restore.emit(item)\" />\n } @else {\n <cw-button label=\"_COMMON._ACTION.DELETE\" [withIcon]=\"spriteIcon.trash\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-delete\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"delete.emit(item)\" />\n }\n }\n </div>\n\n <!-- Restauration impossible : niveau plein (mode excludePendingDeleteFromMax). -->\n @if (item.pendingDelete && isRestoreBlocked(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-restore-blocked-alert\">\n {{ (column()?.restoreBlockedLabel ?? '_COMMON.MAX_RESTORE_BLOCKED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <!-- Corps masqu\u00E9 sur une carte pendingDelete : on n'affiche que l'en-t\u00EAte (carte compacte,\n non pliable, non d\u00E9pla\u00E7able). L'encart \u00AB restauration impossible \u00BB ci-dessus reste, lui, visible. -->\n @if (!item.pendingDelete) {\n <!-- Corps : template custom (slot). Sans slot, on ne rend que ce que l'en-t\u00EAte ne porte\n pas d\u00E9j\u00E0 (le titre vaut `title ?? label`) : le code seul, s'il existe. -->\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item, depth: depth }\" />\n } @else if (item.code) {\n <div class=\"default-item\"><span class=\"text-muted\">({{ item.code }})</span></div>\n }\n\n @if (item.children?.length) {\n <ng-container\n *ngTemplateOutlet=\"nodeTpl; context: { $implicit: item.children, depth: depth + 1, parent: item }\" />\n }\n\n @if (canAdd(item, depth)) {\n <div class=\"d-flex-h justify-end\">\n <cw-button class=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(item.children ?? [], depth + 1)\" (btnAction)=\"onAdd(item, depth + 1)\" />\n </div>\n }\n }\n </cw-card>\n </li>\n }\n\n </ul>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$1.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CardComponent, selector: "cw-card", inputs: ["title", "subtitle", "type", "titleRank", "cssClass", "collapsible", "collapsed", "disabled", "collapseLocked", "collapseStretched", "collapseId", "destroyOnHide"], outputs: ["collapsibleChange", "destroyOnHideChange", "collapseClicked"] }, { kind: "component", type: BadgeComponent, selector: "cw-badge", inputs: ["type", "label", "withIcon", "iconPosition", "cssClass", "skeletonMode", "dataTest"] }, { kind: "component", type: IconComponent, selector: "cw-icon", inputs: ["icon", "label", "type", "iconSize", "iconCssClass", "iconUiType", "iconColorCustom", "spritePath"] }, { kind: "component", type: ButtonComponent, selector: "cw-button", inputs: ["type", "label", "id", "link", "isDropdown", "hideCaret", "withIcon", "withOnlyIcon", "iconSize", "iconPosition", "dropdownPosition", "isMinWidth", "isDisabled", "isLoading", "loadingAnnounce", "cssClass", "dataTest", "skeletonMode", "withTooltip", "tooltipText", "tooltipTitle", "tooltipTrigger", "tooltipPosition", "tooltipType"], outputs: ["btnAction", "dropDownClicked"] }, { kind: "component", type: AlertComponent, selector: "cw-alert", inputs: ["type", "title", "isDismissible", "cssClass", "dataTest"], outputs: ["close"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
345
421
|
}
|
|
346
422
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: DragNDropNestedListComponent, decorators: [{
|
|
347
423
|
type: Component,
|
|
348
|
-
args: [{ selector: 'cw-drag-n-drop-nested-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass, NgTemplateOutlet, TranslateModule, DragDropModule, CardComponent, BadgeComponent, IconComponent, ButtonComponent, AlertComponent], template: "<div class=\"ddn-list d-flex-v gap-md\">\n <div class=\"d-flex-h justify-between\">\n @if (column()?.title) {\n <h2>{{ column()!.title | translate }} ({{ columnCountLabel() }})</h2>\n }\n\n @if (column()?.showAddRoot) {\n <cw-button cssClass=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addRootLabel ?? column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(_items, 0)\" (btnAction)=\"onAdd(undefined, 0)\" />\n }\n </div>\n\n <ng-container *ngTemplateOutlet=\"nodeTpl; context: { $implicit: _items, depth: 0, parent: undefined }\" />\n</div>\n\n<!--\n Template r\u00E9cursif : \u00E0 chaque niveau, on rend un cdkDropList isol\u00E9\n (pas de cdkDropListConnectedTo => transfert inter-listes impossible),\n puis on r\u00E9-instancie le m\u00EAme template pour la sous-liste de chaque enfant.\n-->\n<ng-template #nodeTpl let-nodes let-depth=\"depth\" let-parent=\"parent\">\n @if (isLevelFull(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-max-alert\">\n {{ (column()?.maxReachedLabel ?? '_COMMON.MAX_ITEMS_REACHED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <ul class=\"list-unstyled d-flex-v gap-md ms-none\" [ngClass]=\"column()?.cssClass\" [attr.data-depth]=\"depth\"\n cdkDropList [cdkDropListData]=\"nodes\" (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of nodes; track item.id) {\n <li cdkDrag [cdkDragDisabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" cdkDragPreviewClass=\"ddn-list-card-preview\">\n <cw-card [cssClass]=\"cardCssClass(item)\" [title]=\"(item.title ?? item.label) || ''\"\n [subtitle]=\"item.subtitle ?? ''\" [type]=\"cardType(depth)\" [collapsible]=\"isCollapsible(item, depth)\"\n [collapsed]=\"
|
|
424
|
+
args: [{ selector: 'cw-drag-n-drop-nested-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass, NgTemplateOutlet, TranslateModule, DragDropModule, CardComponent, BadgeComponent, IconComponent, ButtonComponent, AlertComponent], template: "<div class=\"ddn-list d-flex-v gap-md\">\n <div class=\"d-flex-h justify-between\">\n @if (column()?.title) {\n <h2>{{ column()!.title | translate }} ({{ columnCountLabel() }})</h2>\n }\n\n @if (column()?.showAddRoot) {\n <cw-button cssClass=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addRootLabel ?? column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(_items, 0)\" (btnAction)=\"onAdd(undefined, 0)\" />\n }\n </div>\n\n <ng-container *ngTemplateOutlet=\"nodeTpl; context: { $implicit: _items, depth: 0, parent: undefined }\" />\n</div>\n\n<!--\n Template r\u00E9cursif : \u00E0 chaque niveau, on rend un cdkDropList isol\u00E9\n (pas de cdkDropListConnectedTo => transfert inter-listes impossible),\n puis on r\u00E9-instancie le m\u00EAme template pour la sous-liste de chaque enfant.\n-->\n<ng-template #nodeTpl let-nodes let-depth=\"depth\" let-parent=\"parent\">\n @if (isLevelFull(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-max-alert\">\n {{ (column()?.maxReachedLabel ?? '_COMMON.MAX_ITEMS_REACHED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <ul class=\"list-unstyled d-flex-v gap-md ms-none\" [ngClass]=\"column()?.cssClass\" [attr.data-depth]=\"depth\"\n cdkDropList [cdkDropListData]=\"nodes\" (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of nodes; track item.id) {\n <li cdkDrag [cdkDragDisabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" cdkDragPreviewClass=\"ddn-list-card-preview\">\n <cw-card [cssClass]=\"cardCssClass(item, depth)\" [title]=\"(item.title ?? item.label) || ''\"\n [subtitle]=\"item.subtitle ?? ''\" [type]=\"cardType(depth)\" [collapsible]=\"isCollapsible(item, depth)\"\n [collapsed]=\"isCollapsedCard(item, depth)\" [collapseStretched]=\"false\"\n (collapseClicked)=\"onCollapseChange(item, $event)\">\n\n <!-- Poign\u00E9e de drag (\u00E0 gauche du titre) : le glisser ne d\u00E9marre que d'ici -->\n <button header-start type=\"button\" class=\"ddn-list-handle btn btn-ghost\" cdkDragHandle\n [disabled]=\"(item.disabled ?? false) || (item.pendingDelete ?? false)\" [attr.aria-label]=\"'_COMMON._ACTION.MOVE' | translate\">\n <cw-icon [icon]=\"spriteIcon.grip\" [iconSize]=\"iconSize['md']\" />\n </button>\n\n <!-- En-t\u00EAte : compteur d'enfants + badge + actions -->\n <div header-custom-area class=\"d-flex-h gap-2xs justify-end align-start\">\n @if (childrenCountLabel(item, depth); as count) {\n <span class=\"ddn-list-count fs fs-xs\">{{ count }}</span>\n }\n\n @if (item.badge) {\n <cw-badge [type]=\"item.badge.type\" [label]=\"item.badge.label\" [withIcon]=\"item.badge.icon\" />\n }\n\n <!-- Sur une carte pendingDelete, seul \u00AB Restaurer \u00BB est propos\u00E9 (view/edit masqu\u00E9s). -->\n @if (!item.pendingDelete && showAction(item, 'view')) {\n <cw-button label=\"_COMMON._ACTION.VIEW\" [withIcon]=\"spriteIcon.search\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"view.emit(item)\" />\n }\n @if (!item.pendingDelete && showAction(item, 'edit')) {\n <cw-button label=\"_COMMON._ACTION.EDIT\" [withIcon]=\"spriteIcon.edit\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"edit.emit(item)\" />\n }\n @if (showAction(item, 'delete')) {\n @if (item.pendingDelete) {\n <!-- Soft-delete : la corbeille bascule en \u00AB Restaurer \u00BB (d\u00E9sactiv\u00E9 si le niveau est plein). -->\n <cw-button label=\"_COMMON._ACTION.RESTORE\" [withIcon]=\"spriteIcon.toolbarRefresh\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-restore\"\n [isDisabled]=\"isRestoreBlocked(nodes, depth)\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"restore.emit(item)\" />\n } @else {\n <cw-button label=\"_COMMON._ACTION.DELETE\" [withIcon]=\"spriteIcon.trash\" [withOnlyIcon]=\"true\"\n [type]=\"buttonType.secondary\" cssClass=\"ddn-list-action-delete\"\n [iconSize]=\"buttonIconSize.xsmall\" (btnAction)=\"delete.emit(item)\" />\n }\n }\n </div>\n\n <!-- Restauration impossible : niveau plein (mode excludePendingDeleteFromMax). -->\n @if (item.pendingDelete && isRestoreBlocked(nodes, depth)) {\n <cw-alert [type]=\"alertType.warning\" cssClass=\"ddn-list-restore-blocked-alert\">\n {{ (column()?.restoreBlockedLabel ?? '_COMMON.MAX_RESTORE_BLOCKED') | translate:{ max: levelMax(depth) } }}\n </cw-alert>\n }\n\n <!-- Corps masqu\u00E9 sur une carte pendingDelete : on n'affiche que l'en-t\u00EAte (carte compacte,\n non pliable, non d\u00E9pla\u00E7able). L'encart \u00AB restauration impossible \u00BB ci-dessus reste, lui, visible. -->\n @if (!item.pendingDelete) {\n <!-- Corps : template custom (slot). Sans slot, on ne rend que ce que l'en-t\u00EAte ne porte\n pas d\u00E9j\u00E0 (le titre vaut `title ?? label`) : le code seul, s'il existe. -->\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item, depth: depth }\" />\n } @else if (item.code) {\n <div class=\"default-item\"><span class=\"text-muted\">({{ item.code }})</span></div>\n }\n\n @if (item.children?.length) {\n <ng-container\n *ngTemplateOutlet=\"nodeTpl; context: { $implicit: item.children, depth: depth + 1, parent: item }\" />\n }\n\n @if (canAdd(item, depth)) {\n <div class=\"d-flex-h justify-end\">\n <cw-button class=\"ddn-list-add\" [type]=\"buttonType.link\" [withIcon]=\"spriteIcon.add\"\n [iconPosition]=\"buttonPosition.left\" [label]=\"column()?.addLabel ?? '_COMMON._ACTION.ADD'\"\n [isDisabled]=\"isLevelFull(item.children ?? [], depth + 1)\" (btnAction)=\"onAdd(item, depth + 1)\" />\n </div>\n }\n }\n </cw-card>\n </li>\n }\n\n </ul>\n</ng-template>\n" }]
|
|
349
425
|
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: false }] }], reorderOnDrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderOnDrop", required: false }] }], maxDepth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDepth", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }], itemsChange: [{ type: i0.Output, args: ["itemsChange"] }], view: [{ type: i0.Output, args: ["view"] }], edit: [{ type: i0.Output, args: ["edit"] }], delete: [{ type: i0.Output, args: ["delete"] }], restore: [{ type: i0.Output, args: ["restore"] }], add: [{ type: i0.Output, args: ["add"] }] } });
|
|
350
426
|
|
|
351
427
|
class PaginationComponent {
|
|
@@ -771,7 +847,7 @@ class TableComponent {
|
|
|
771
847
|
return typeof descriptor.link === 'function' ? descriptor.link(row) : descriptor.link;
|
|
772
848
|
}
|
|
773
849
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
774
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.20", type: TableComponent, isStandalone: true, selector: "cw-table", inputs: { checkbox: { classPropertyName: "checkbox", publicName: "checkbox", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowClassFn: { classPropertyName: "rowClassFn", publicName: "rowClassFn", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, bulkActions: { classPropertyName: "bulkActions", publicName: "bulkActions", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, emptyStateNoData: { classPropertyName: "emptyStateNoData", publicName: "emptyStateNoData", isSignal: true, isRequired: false, transformFunction: null }, emptyStateNoResult: { classPropertyName: "emptyStateNoResult", publicName: "emptyStateNoResult", isSignal: true, isRequired: false, transformFunction: null }, isFiltered: { classPropertyName: "isFiltered", publicName: "isFiltered", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellClick: "cellClick", sortChange: "sortChange", selectionChange: "selectionChange", paginationChange: "paginationChange", bulkDelete: "bulkDelete", bulkAction: "bulkAction" }, host: { classAttribute: "cw-table" }, queries: [{ propertyName: "actionsTemplate", first: true, predicate: ["actionsTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (checkbox() && selectedRows().size > 0) {\n <div class=\"table-selection-info mb-2 d-flex align-items-center gap-2 flex-wrap\">\n <span>\n {{ selectedRows().size }} {{ '_COMMON._TABLE._BULK_ACTION.SELECTED_ITEMS_CURRENT_PAGE' | translate }}\n </span>\n @for (action of bulkActions(); track $index) {\n <cw-button\n [type]=\"resolveVariant(action)\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"resolveDisabled(action)\"\n (btnAction)=\"onBulkActionClick(action)\">\n </cw-button>\n }\n </div>\n}\n\n<div class=\"table-responsive\">\n <table class=\"table\">\n <caption class=\"visually-hidden\" [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: title() } \"></caption>\n <thead>\n <tr>\n @if(checkbox()) {\n <th scope=\"col\" width=\"10\">\n <div class=\"field-check\">\n <input class=\"field-check-input\" type=\"checkbox\" [id]=\"uid + '-all'\" [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\" (change)=\"toggleAll()\">\n <label class=\"field-check-label\" [for]=\"uid + '-all'\">\n <span class=\"visually-hidden\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }}</span>\n </label>\n </div>\n </th>\n }\n\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <th scope=\"col\" [class.p-0]=\"column.sort\" [attr.aria-sort]=\"column.sort ? getAriaSort(column.key) : null\">\n @if (column.sort) {\n <button class=\"d-flex-h gap-2xs\" [class]=\"getSortClass(column.key)\" (click)=\"setSortProperty(column.key)\">\n {{ column.label | translate}}\n <cw-icon\n [icon]=\"getSortIcon(column.key)\"\n [label]=\"'_COMMON._TABLE._SORT.LABEL' | translate\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['xs']\"></cw-icon>\n </button>\n }\n @else {\n {{ column.label | translate }}\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td [attr.colspan]=\"visibleColumnCount()\">\n <cw-loader></cw-loader>\n </td>\n </tr>\n }\n @else if (!data() || data().length === 0) {\n <tr>\n <td class=\"table-info no-result\" [attr.colspan]=\"visibleColumnCount()\">\n @if (currentEmptyState(); as empty) {\n <cw-empty-state\n [illustration]=\"empty.illustration ?? (isFiltered() ? illustrationEnum.noResult : illustrationEnum.noData)\"\n [imageSource]=\"empty.imageSource\"\n [title]=\"empty.title\"\n [description]=\"empty.description\"\n [primaryButton]=\"empty.primaryButton\"\n [secondaryButton]=\"empty.secondaryButton\"\n (primaryClick)=\"empty.primaryButton?.click?.()\"\n (secondaryClick)=\"empty.secondaryButton?.click?.()\">\n </cw-empty-state>\n } @else {\n {{ '_COMMON._TABLE.NO_RESULT' | translate }}\n }\n </td>\n </tr>\n }\n @else {\n @for (row of data(); track row) {\n <tr [class.tr-selected]=\"isSelected(row)\" [class]=\"getRowClass(row)\">\n @if (checkbox()) {\n <td>\n <input class=\"field-check-input\" type=\"checkbox\" [checked]=\"isSelected(row)\" (change)=\"toggleRow(row)\" [id]=\"uid + '-check-' + row.id\"\n [attr.aria-label]=\"('_COMMON._TABLE._THEAD.CHECK_LINE' | translate) + ' ' + row.id\">\n <label class=\"visually-hidden\" [for]=\"uid + '-check-' + row.id\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }} {{ row.id }}</label>\n </td>\n }\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <td [class.text-end]=\"column.align === 'right'\" [class.text-center]=\"column.align === 'center'\"\n [class.td-actions]=\"column.type === 'actions'\">\n @switch (column.type) {\n @case ('link') {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </a>\n }\n @case ('badge') {\n <cw-badge\n [type]=\"getBadge(column, row[column.key]).type\"\n [label]=\"getBadge(column, row[column.key]).label ?? row[column.key]\"\n [withIcon]=\"getBadge(column, row[column.key]).withIcon\"\n [iconPosition]=\"getBadge(column, row[column.key]).iconPosition\"></cw-badge>\n }\n @case ('icon') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n </a>\n } @else {\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n }\n }\n @case ('image') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n </a>\n } @else {\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n }\n }\n @case ('check') {\n @if (isTruthy(row[column.key])) {\n <cw-icon\n [icon]=\"spriteIcon.checkCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.YES' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-success\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n } @else {\n <cw-icon\n [icon]=\"spriteIcon.closeCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.NO' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-danger\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n }\n }\n @case ('progressbar') {\n <div class=\"td-progressbar\">\n <cw-progress-bar\n [value]=\"row[column.key]\"\n [size]=\"progressBarSize.sm\"\n [type]=\"progressBarType.information\"></cw-progress-bar>\n <span class=\"td-progressbar-value\">{{ row[column.key] }}%</span>\n </div>\n }\n @case ('actions') {\n @if (usingRowActions) {\n @let actions = getResolvedActions(row);\n @if (actions.length > 0) {\n @if (!useDropdownActions()) {\n @for (action of actions; track $index) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n } @else {\n <cw-button\n [label]=\"'_COMMON._TABLE.ACTIONS_MENU'\"\n [withIcon]=\"spriteIcon.menuVertical\"\n [withOnlyIcon]=\"true\"\n [type]=\"buttonType.ghost\"\n [isDropdown]=\"true\"\n [hideCaret]=\"true\">\n <ul class=\"p-0 m-0\">\n @for (action of actions; track $index) {\n <li>\n @if (action.link) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\">\n </cw-button>\n } @else {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n </li>\n }\n </ul>\n </cw-button>\n }\n }\n } @else {\n <ng-container\n *ngTemplateOutlet=\"actionsTemplate(); context: { $implicit: row }\">\n </ng-container>\n }\n }\n @default {\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n }\n }\n </td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (pagination()) {\n <cw-pagination\n [pagination]=\"pagination()!\"\n (paginationChange)=\"paginationChange.emit($event)\">\n </cw-pagination>\n}\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "component", type: LoaderComponent, selector: "cw-loader", inputs: ["size", "displayText"] }, { kind: "component", type: BadgeComponent, selector: "cw-badge", inputs: ["type", "label", "withIcon", "iconPosition", "cssClass", "skeletonMode", "dataTest"] }, { kind: "component", type: ButtonComponent, selector: "cw-button", inputs: ["type", "label", "id", "link", "isDropdown", "hideCaret", "withIcon", "withOnlyIcon", "iconSize", "iconPosition", "dropdownPosition", "isMinWidth", "isDisabled", "isLoading", "loadingAnnounce", "cssClass", "dataTest", "skeletonMode", "withTooltip", "tooltipText", "tooltipTitle", "tooltipTrigger", "tooltipPosition", "tooltipType"], outputs: ["btnAction", "dropDownClicked"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PaginationComponent, selector: "cw-pagination", inputs: ["pagination"], outputs: ["paginationChange"] }, { kind: "component", type: IconComponent, selector: "cw-icon", inputs: ["icon", "label", "type", "iconSize", "iconCssClass", "iconUiType", "iconColorCustom", "spritePath"] }, { kind: "component", type: ImageComponent, selector: "cw-image", inputs: ["source", "alt", "isAriaHidden", "cssClass", "width", "height"] }, { kind: "component", type: EmptyStateComponent, selector: "cw-empty-state", inputs: ["illustration", "illustrationBasePath", "imageSource", "imageAlt", "title", "description", "primaryButton", "secondaryButton", "dataTest"], outputs: ["primaryClick", "secondaryClick"] }, { kind: "component", type: ProgressBarComponent, selector: "cw-progress-bar", inputs: ["value", "max", "size", "type", "showValue", "label", "dataTest"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
850
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.20", type: TableComponent, isStandalone: true, selector: "cw-table", inputs: { checkbox: { classPropertyName: "checkbox", publicName: "checkbox", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowClassFn: { classPropertyName: "rowClassFn", publicName: "rowClassFn", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, bulkActions: { classPropertyName: "bulkActions", publicName: "bulkActions", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, emptyStateNoData: { classPropertyName: "emptyStateNoData", publicName: "emptyStateNoData", isSignal: true, isRequired: false, transformFunction: null }, emptyStateNoResult: { classPropertyName: "emptyStateNoResult", publicName: "emptyStateNoResult", isSignal: true, isRequired: false, transformFunction: null }, isFiltered: { classPropertyName: "isFiltered", publicName: "isFiltered", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellClick: "cellClick", sortChange: "sortChange", selectionChange: "selectionChange", paginationChange: "paginationChange", bulkDelete: "bulkDelete", bulkAction: "bulkAction" }, host: { classAttribute: "cw-table" }, queries: [{ propertyName: "actionsTemplate", first: true, predicate: ["actionsTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (checkbox() && selectedRows().size > 0) {\n <!-- Espacement DS : gap-md = 16px = component/button/set/gap (espacement entre\n boutons d'un set). Utilitaires basic-ui (adosses a l'echelle $sizing des\n tokens) et non ceux de Bootstrap : gap-2 valait 8px. d-flex-h centre deja\n verticalement, align-items-center est donc inutile. -->\n <div class=\"table-selection-info mb-md d-flex-h gap-md flex-wrap\">\n <span class=\"flex-grow-1\">\n {{ selectedRows().size }} {{ '_COMMON._TABLE._BULK_ACTION.SELECTED_ITEMS_CURRENT_PAGE' | translate }}\n </span>\n @for (action of bulkActions(); track $index) {\n <cw-button\n [type]=\"resolveVariant(action)\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"resolveDisabled(action)\"\n (btnAction)=\"onBulkActionClick(action)\">\n </cw-button>\n }\n </div>\n}\n\n<div class=\"table-responsive\">\n <table class=\"table\">\n <caption class=\"visually-hidden\" [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: title() } \"></caption>\n <thead>\n <tr>\n @if(checkbox()) {\n <th scope=\"col\" width=\"10\">\n <div class=\"field-check\">\n <input class=\"field-check-input\" type=\"checkbox\" [id]=\"uid + '-all'\" [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\" (change)=\"toggleAll()\">\n <label class=\"field-check-label\" [for]=\"uid + '-all'\">\n <span class=\"visually-hidden\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }}</span>\n </label>\n </div>\n </th>\n }\n\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <th scope=\"col\" [class.p-0]=\"column.sort\" [attr.aria-sort]=\"column.sort ? getAriaSort(column.key) : null\">\n @if (column.sort) {\n <button class=\"d-flex-h gap-2xs\" [class]=\"getSortClass(column.key)\" (click)=\"setSortProperty(column.key)\">\n {{ column.label | translate}}\n <cw-icon\n [icon]=\"getSortIcon(column.key)\"\n [label]=\"'_COMMON._TABLE._SORT.LABEL' | translate\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['xs']\"></cw-icon>\n </button>\n }\n @else {\n {{ column.label | translate }}\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td [attr.colspan]=\"visibleColumnCount()\">\n <cw-loader></cw-loader>\n </td>\n </tr>\n }\n @else if (!data() || data().length === 0) {\n <tr>\n <td class=\"table-info no-result\" [attr.colspan]=\"visibleColumnCount()\">\n @if (currentEmptyState(); as empty) {\n <cw-empty-state\n [illustration]=\"empty.illustration ?? (isFiltered() ? illustrationEnum.noResult : illustrationEnum.noData)\"\n [imageSource]=\"empty.imageSource\"\n [title]=\"empty.title\"\n [description]=\"empty.description\"\n [primaryButton]=\"empty.primaryButton\"\n [secondaryButton]=\"empty.secondaryButton\"\n (primaryClick)=\"empty.primaryButton?.click?.()\"\n (secondaryClick)=\"empty.secondaryButton?.click?.()\">\n </cw-empty-state>\n } @else {\n {{ '_COMMON._TABLE.NO_RESULT' | translate }}\n }\n </td>\n </tr>\n }\n @else {\n @for (row of data(); track row) {\n <tr [class.tr-selected]=\"isSelected(row)\" [class]=\"getRowClass(row)\">\n @if (checkbox()) {\n <td>\n <input class=\"field-check-input\" type=\"checkbox\" [checked]=\"isSelected(row)\" (change)=\"toggleRow(row)\" [id]=\"uid + '-check-' + row.id\"\n [attr.aria-label]=\"('_COMMON._TABLE._THEAD.CHECK_LINE' | translate) + ' ' + row.id\">\n <label class=\"visually-hidden\" [for]=\"uid + '-check-' + row.id\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }} {{ row.id }}</label>\n </td>\n }\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <td [class.text-end]=\"column.align === 'right'\" [class.text-center]=\"column.align === 'center'\"\n [class.td-actions]=\"column.type === 'actions'\">\n @switch (column.type) {\n @case ('link') {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </a>\n }\n @case ('badge') {\n <cw-badge\n [type]=\"getBadge(column, row[column.key]).type\"\n [label]=\"getBadge(column, row[column.key]).label ?? row[column.key]\"\n [withIcon]=\"getBadge(column, row[column.key]).withIcon\"\n [iconPosition]=\"getBadge(column, row[column.key]).iconPosition\"></cw-badge>\n }\n @case ('icon') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n </a>\n } @else {\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n }\n }\n @case ('image') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n </a>\n } @else {\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n }\n }\n @case ('check') {\n @if (isTruthy(row[column.key])) {\n <cw-icon\n [icon]=\"spriteIcon.checkCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.YES' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-success\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n } @else {\n <cw-icon\n [icon]=\"spriteIcon.closeCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.NO' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-danger\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n }\n }\n @case ('progressbar') {\n <div class=\"td-progressbar\">\n <cw-progress-bar\n [value]=\"row[column.key]\"\n [size]=\"progressBarSize.sm\"\n [type]=\"progressBarType.information\"></cw-progress-bar>\n <span class=\"td-progressbar-value\">{{ row[column.key] }}%</span>\n </div>\n }\n @case ('actions') {\n @if (usingRowActions) {\n @let actions = getResolvedActions(row);\n @if (actions.length > 0) {\n @if (!useDropdownActions()) {\n @for (action of actions; track $index) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n } @else {\n <cw-button\n [label]=\"'_COMMON._TABLE.ACTIONS_MENU'\"\n [withIcon]=\"spriteIcon.menuVertical\"\n [withOnlyIcon]=\"true\"\n [type]=\"buttonType.ghost\"\n [isDropdown]=\"true\"\n [hideCaret]=\"true\">\n <ul class=\"p-0 m-0\">\n @for (action of actions; track $index) {\n <li>\n @if (action.link) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\">\n </cw-button>\n } @else {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n </li>\n }\n </ul>\n </cw-button>\n }\n }\n } @else {\n <ng-container\n *ngTemplateOutlet=\"actionsTemplate(); context: { $implicit: row }\">\n </ng-container>\n }\n }\n @default {\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n }\n }\n </td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (pagination()) {\n <cw-pagination\n [pagination]=\"pagination()!\"\n (paginationChange)=\"paginationChange.emit($event)\">\n </cw-pagination>\n}\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "component", type: LoaderComponent, selector: "cw-loader", inputs: ["size", "displayText"] }, { kind: "component", type: BadgeComponent, selector: "cw-badge", inputs: ["type", "label", "withIcon", "iconPosition", "cssClass", "skeletonMode", "dataTest"] }, { kind: "component", type: ButtonComponent, selector: "cw-button", inputs: ["type", "label", "id", "link", "isDropdown", "hideCaret", "withIcon", "withOnlyIcon", "iconSize", "iconPosition", "dropdownPosition", "isMinWidth", "isDisabled", "isLoading", "loadingAnnounce", "cssClass", "dataTest", "skeletonMode", "withTooltip", "tooltipText", "tooltipTitle", "tooltipTrigger", "tooltipPosition", "tooltipType"], outputs: ["btnAction", "dropDownClicked"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PaginationComponent, selector: "cw-pagination", inputs: ["pagination"], outputs: ["paginationChange"] }, { kind: "component", type: IconComponent, selector: "cw-icon", inputs: ["icon", "label", "type", "iconSize", "iconCssClass", "iconUiType", "iconColorCustom", "spritePath"] }, { kind: "component", type: ImageComponent, selector: "cw-image", inputs: ["source", "alt", "isAriaHidden", "cssClass", "width", "height"] }, { kind: "component", type: EmptyStateComponent, selector: "cw-empty-state", inputs: ["illustration", "illustrationBasePath", "imageSource", "imageAlt", "title", "description", "primaryButton", "secondaryButton", "dataTest"], outputs: ["primaryClick", "secondaryClick"] }, { kind: "component", type: ProgressBarComponent, selector: "cw-progress-bar", inputs: ["value", "max", "size", "type", "showValue", "label", "dataTest"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
775
851
|
}
|
|
776
852
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: TableComponent, decorators: [{
|
|
777
853
|
type: Component,
|
|
@@ -786,7 +862,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.20", ngImpo
|
|
|
786
862
|
ImageComponent,
|
|
787
863
|
EmptyStateComponent,
|
|
788
864
|
ProgressBarComponent
|
|
789
|
-
], template: "@if (checkbox() && selectedRows().size > 0) {\n <div class=\"table-selection-info mb-2 d-flex align-items-center gap-2 flex-wrap\">\n <span>\n {{ selectedRows().size }} {{ '_COMMON._TABLE._BULK_ACTION.SELECTED_ITEMS_CURRENT_PAGE' | translate }}\n </span>\n @for (action of bulkActions(); track $index) {\n <cw-button\n [type]=\"resolveVariant(action)\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"resolveDisabled(action)\"\n (btnAction)=\"onBulkActionClick(action)\">\n </cw-button>\n }\n </div>\n}\n\n<div class=\"table-responsive\">\n <table class=\"table\">\n <caption class=\"visually-hidden\" [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: title() } \"></caption>\n <thead>\n <tr>\n @if(checkbox()) {\n <th scope=\"col\" width=\"10\">\n <div class=\"field-check\">\n <input class=\"field-check-input\" type=\"checkbox\" [id]=\"uid + '-all'\" [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\" (change)=\"toggleAll()\">\n <label class=\"field-check-label\" [for]=\"uid + '-all'\">\n <span class=\"visually-hidden\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }}</span>\n </label>\n </div>\n </th>\n }\n\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <th scope=\"col\" [class.p-0]=\"column.sort\" [attr.aria-sort]=\"column.sort ? getAriaSort(column.key) : null\">\n @if (column.sort) {\n <button class=\"d-flex-h gap-2xs\" [class]=\"getSortClass(column.key)\" (click)=\"setSortProperty(column.key)\">\n {{ column.label | translate}}\n <cw-icon\n [icon]=\"getSortIcon(column.key)\"\n [label]=\"'_COMMON._TABLE._SORT.LABEL' | translate\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['xs']\"></cw-icon>\n </button>\n }\n @else {\n {{ column.label | translate }}\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td [attr.colspan]=\"visibleColumnCount()\">\n <cw-loader></cw-loader>\n </td>\n </tr>\n }\n @else if (!data() || data().length === 0) {\n <tr>\n <td class=\"table-info no-result\" [attr.colspan]=\"visibleColumnCount()\">\n @if (currentEmptyState(); as empty) {\n <cw-empty-state\n [illustration]=\"empty.illustration ?? (isFiltered() ? illustrationEnum.noResult : illustrationEnum.noData)\"\n [imageSource]=\"empty.imageSource\"\n [title]=\"empty.title\"\n [description]=\"empty.description\"\n [primaryButton]=\"empty.primaryButton\"\n [secondaryButton]=\"empty.secondaryButton\"\n (primaryClick)=\"empty.primaryButton?.click?.()\"\n (secondaryClick)=\"empty.secondaryButton?.click?.()\">\n </cw-empty-state>\n } @else {\n {{ '_COMMON._TABLE.NO_RESULT' | translate }}\n }\n </td>\n </tr>\n }\n @else {\n @for (row of data(); track row) {\n <tr [class.tr-selected]=\"isSelected(row)\" [class]=\"getRowClass(row)\">\n @if (checkbox()) {\n <td>\n <input class=\"field-check-input\" type=\"checkbox\" [checked]=\"isSelected(row)\" (change)=\"toggleRow(row)\" [id]=\"uid + '-check-' + row.id\"\n [attr.aria-label]=\"('_COMMON._TABLE._THEAD.CHECK_LINE' | translate) + ' ' + row.id\">\n <label class=\"visually-hidden\" [for]=\"uid + '-check-' + row.id\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }} {{ row.id }}</label>\n </td>\n }\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <td [class.text-end]=\"column.align === 'right'\" [class.text-center]=\"column.align === 'center'\"\n [class.td-actions]=\"column.type === 'actions'\">\n @switch (column.type) {\n @case ('link') {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </a>\n }\n @case ('badge') {\n <cw-badge\n [type]=\"getBadge(column, row[column.key]).type\"\n [label]=\"getBadge(column, row[column.key]).label ?? row[column.key]\"\n [withIcon]=\"getBadge(column, row[column.key]).withIcon\"\n [iconPosition]=\"getBadge(column, row[column.key]).iconPosition\"></cw-badge>\n }\n @case ('icon') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n </a>\n } @else {\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n }\n }\n @case ('image') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n </a>\n } @else {\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n }\n }\n @case ('check') {\n @if (isTruthy(row[column.key])) {\n <cw-icon\n [icon]=\"spriteIcon.checkCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.YES' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-success\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n } @else {\n <cw-icon\n [icon]=\"spriteIcon.closeCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.NO' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-danger\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n }\n }\n @case ('progressbar') {\n <div class=\"td-progressbar\">\n <cw-progress-bar\n [value]=\"row[column.key]\"\n [size]=\"progressBarSize.sm\"\n [type]=\"progressBarType.information\"></cw-progress-bar>\n <span class=\"td-progressbar-value\">{{ row[column.key] }}%</span>\n </div>\n }\n @case ('actions') {\n @if (usingRowActions) {\n @let actions = getResolvedActions(row);\n @if (actions.length > 0) {\n @if (!useDropdownActions()) {\n @for (action of actions; track $index) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n } @else {\n <cw-button\n [label]=\"'_COMMON._TABLE.ACTIONS_MENU'\"\n [withIcon]=\"spriteIcon.menuVertical\"\n [withOnlyIcon]=\"true\"\n [type]=\"buttonType.ghost\"\n [isDropdown]=\"true\"\n [hideCaret]=\"true\">\n <ul class=\"p-0 m-0\">\n @for (action of actions; track $index) {\n <li>\n @if (action.link) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\">\n </cw-button>\n } @else {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n </li>\n }\n </ul>\n </cw-button>\n }\n }\n } @else {\n <ng-container\n *ngTemplateOutlet=\"actionsTemplate(); context: { $implicit: row }\">\n </ng-container>\n }\n }\n @default {\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n }\n }\n </td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (pagination()) {\n <cw-pagination\n [pagination]=\"pagination()!\"\n (paginationChange)=\"paginationChange.emit($event)\">\n </cw-pagination>\n}\n" }]
|
|
865
|
+
], template: "@if (checkbox() && selectedRows().size > 0) {\n <!-- Espacement DS : gap-md = 16px = component/button/set/gap (espacement entre\n boutons d'un set). Utilitaires basic-ui (adosses a l'echelle $sizing des\n tokens) et non ceux de Bootstrap : gap-2 valait 8px. d-flex-h centre deja\n verticalement, align-items-center est donc inutile. -->\n <div class=\"table-selection-info mb-md d-flex-h gap-md flex-wrap\">\n <span class=\"flex-grow-1\">\n {{ selectedRows().size }} {{ '_COMMON._TABLE._BULK_ACTION.SELECTED_ITEMS_CURRENT_PAGE' | translate }}\n </span>\n @for (action of bulkActions(); track $index) {\n <cw-button\n [type]=\"resolveVariant(action)\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"resolveDisabled(action)\"\n (btnAction)=\"onBulkActionClick(action)\">\n </cw-button>\n }\n </div>\n}\n\n<div class=\"table-responsive\">\n <table class=\"table\">\n <caption class=\"visually-hidden\" [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: title() } \"></caption>\n <thead>\n <tr>\n @if(checkbox()) {\n <th scope=\"col\" width=\"10\">\n <div class=\"field-check\">\n <input class=\"field-check-input\" type=\"checkbox\" [id]=\"uid + '-all'\" [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\" (change)=\"toggleAll()\">\n <label class=\"field-check-label\" [for]=\"uid + '-all'\">\n <span class=\"visually-hidden\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }}</span>\n </label>\n </div>\n </th>\n }\n\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <th scope=\"col\" [class.p-0]=\"column.sort\" [attr.aria-sort]=\"column.sort ? getAriaSort(column.key) : null\">\n @if (column.sort) {\n <button class=\"d-flex-h gap-2xs\" [class]=\"getSortClass(column.key)\" (click)=\"setSortProperty(column.key)\">\n {{ column.label | translate}}\n <cw-icon\n [icon]=\"getSortIcon(column.key)\"\n [label]=\"'_COMMON._TABLE._SORT.LABEL' | translate\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['xs']\"></cw-icon>\n </button>\n }\n @else {\n {{ column.label | translate }}\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n <tr>\n <td [attr.colspan]=\"visibleColumnCount()\">\n <cw-loader></cw-loader>\n </td>\n </tr>\n }\n @else if (!data() || data().length === 0) {\n <tr>\n <td class=\"table-info no-result\" [attr.colspan]=\"visibleColumnCount()\">\n @if (currentEmptyState(); as empty) {\n <cw-empty-state\n [illustration]=\"empty.illustration ?? (isFiltered() ? illustrationEnum.noResult : illustrationEnum.noData)\"\n [imageSource]=\"empty.imageSource\"\n [title]=\"empty.title\"\n [description]=\"empty.description\"\n [primaryButton]=\"empty.primaryButton\"\n [secondaryButton]=\"empty.secondaryButton\"\n (primaryClick)=\"empty.primaryButton?.click?.()\"\n (secondaryClick)=\"empty.secondaryButton?.click?.()\">\n </cw-empty-state>\n } @else {\n {{ '_COMMON._TABLE.NO_RESULT' | translate }}\n }\n </td>\n </tr>\n }\n @else {\n @for (row of data(); track row) {\n <tr [class.tr-selected]=\"isSelected(row)\" [class]=\"getRowClass(row)\">\n @if (checkbox()) {\n <td>\n <input class=\"field-check-input\" type=\"checkbox\" [checked]=\"isSelected(row)\" (change)=\"toggleRow(row)\" [id]=\"uid + '-check-' + row.id\"\n [attr.aria-label]=\"('_COMMON._TABLE._THEAD.CHECK_LINE' | translate) + ' ' + row.id\">\n <label class=\"visually-hidden\" [for]=\"uid + '-check-' + row.id\">{{ '_COMMON._TABLE._THEAD.CHECK_LINE' | translate }} {{ row.id }}</label>\n </td>\n }\n @for (column of columns(); track column.key) {\n @if (!column.hidden) {\n <td [class.text-end]=\"column.align === 'right'\" [class.text-center]=\"column.align === 'center'\"\n [class.td-actions]=\"column.type === 'actions'\">\n @switch (column.type) {\n @case ('link') {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </a>\n }\n @case ('badge') {\n <cw-badge\n [type]=\"getBadge(column, row[column.key]).type\"\n [label]=\"getBadge(column, row[column.key]).label ?? row[column.key]\"\n [withIcon]=\"getBadge(column, row[column.key]).withIcon\"\n [iconPosition]=\"getBadge(column, row[column.key]).iconPosition\"></cw-badge>\n }\n @case ('icon') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n </a>\n } @else {\n <cw-icon\n [icon]=\"row[column.key].icon\"\n [label]=\"row[column.key].label\"\n [type]=\"iconType.default\"\n [iconSize]=\"iconSize['md']\"\n [iconCssClass]=\"row[column.key].iconCssClass\"\n ></cw-icon>\n }\n }\n @case ('image') {\n @if (isClickable(column)) {\n <a href=\"javascript:void(0)\" (click)=\"onCellClick(row, column)\" [attr.aria-label]=\"row[column.key].label\">\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n </a>\n } @else {\n <cw-image\n [source]=\"row[column.key].source\"\n [alt]=\"row[column.key].label\"\n [isAriaHidden]=\"true\"\n [cssClass]=\"row[column.key].iconCssClass\"\n width=\"32\"\n height=\"32\"\n ></cw-image>\n }\n }\n @case ('check') {\n @if (isTruthy(row[column.key])) {\n <cw-icon\n [icon]=\"spriteIcon.checkCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.YES' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-success\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n } @else {\n <cw-icon\n [icon]=\"spriteIcon.closeCircle\"\n [label]=\"'_COMMON._PRO_SENTENCE.NO' | translate\"\n [type]=\"iconType.default\"\n iconCssClass=\"text-danger\"\n [iconSize]=\"iconSize['md']\"></cw-icon>\n }\n }\n @case ('progressbar') {\n <div class=\"td-progressbar\">\n <cw-progress-bar\n [value]=\"row[column.key]\"\n [size]=\"progressBarSize.sm\"\n [type]=\"progressBarType.information\"></cw-progress-bar>\n <span class=\"td-progressbar-value\">{{ row[column.key] }}%</span>\n </div>\n }\n @case ('actions') {\n @if (usingRowActions) {\n @let actions = getResolvedActions(row);\n @if (actions.length > 0) {\n @if (!useDropdownActions()) {\n @for (action of actions; track $index) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n } @else {\n <cw-button\n [label]=\"'_COMMON._TABLE.ACTIONS_MENU'\"\n [withIcon]=\"spriteIcon.menuVertical\"\n [withOnlyIcon]=\"true\"\n [type]=\"buttonType.ghost\"\n [isDropdown]=\"true\"\n [hideCaret]=\"true\">\n <ul class=\"p-0 m-0\">\n @for (action of actions; track $index) {\n <li>\n @if (action.link) {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [link]=\"action.link\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\">\n </cw-button>\n } @else {\n <cw-button\n [type]=\"buttonType.ghost\"\n [label]=\"action.label\"\n [withIcon]=\"action.icon\"\n [isDisabled]=\"action.disabled\"\n [cssClass]=\"'dropdown-item ' + actionCssClass(action)\"\n (btnAction)=\"onRowActionClick(action, row)\">\n </cw-button>\n }\n </li>\n }\n </ul>\n </cw-button>\n }\n }\n } @else {\n <ng-container\n *ngTemplateOutlet=\"actionsTemplate(); context: { $implicit: row }\">\n </ng-container>\n }\n }\n @default {\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n }\n }\n </td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (pagination()) {\n <cw-pagination\n [pagination]=\"pagination()!\"\n (paginationChange)=\"paginationChange.emit($event)\">\n </cw-pagination>\n}\n" }]
|
|
790
866
|
}], ctorParameters: () => [], propDecorators: { checkbox: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkbox", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowClassFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClassFn", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], bulkActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "bulkActions", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], emptyStateNoData: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateNoData", required: false }] }], emptyStateNoResult: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateNoResult", required: false }] }], isFiltered: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFiltered", required: false }] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], paginationChange: [{ type: i0.Output, args: ["paginationChange"] }], bulkDelete: [{ type: i0.Output, args: ["bulkDelete"] }], bulkAction: [{ type: i0.Output, args: ["bulkAction"] }], actionsTemplate: [{ type: i0.ContentChild, args: ['actionsTemplate', { isSignal: true }] }] } });
|
|
791
867
|
|
|
792
868
|
const RANGE_TYPES = new Set([
|