@cityway/bo-ui 1.1.0-beta013 → 1.1.0-beta015

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
@@ -30,7 +30,7 @@ Dépend de `@cityway/basic-ui` (badge, button, icon, image, loader, modale de su
30
30
  | `columns` | `TableColumn[]` | `[]` | Définition des colonnes (voir §3). |
31
31
  | `data` | `any[]` | `[]` | Lignes à afficher. |
32
32
  | `checkbox` | `boolean` | `false` | Active la colonne de sélection. |
33
- | `title` | `string` | `''` | Titre du tableau. |
33
+ | `title` | `string` | `''` | Titre du tableau. Passé au pipe `translate` → fournir une **clé i18n**. Alimente le `<caption>` (lu par les lecteurs d'écran, masqué visuellement). |
34
34
  | `loading` | `boolean` | `false` | Affiche le loader. |
35
35
  | `rowClassFn` | `(row) => string` | `undefined` | Classe CSS calculée par ligne. |
36
36
  | `pagination` | `Pagination` | `undefined` | Config de pagination (intègre `cw-pagination`). |
@@ -46,11 +46,36 @@ Dépend de `@cityway/basic-ui` (badge, button, icon, image, loader, modale de su
46
46
  |--------|---------|-------------|
47
47
  | `cellClick` | `CellClickEvent` | Clic sur une cellule cliquable/lien. |
48
48
  | `sortChange` | `SortEvent` | Changement de tri (`{ key, direction }`). |
49
- | `selectionChange` | `any[]` | Lignes sélectionnées. |
49
+ | `selectionChange` | `any[]` | Lignes sélectionnées. Émis aussi bien par un clic utilisateur que par `selectRows()` / `clearSelection()`. |
50
50
  | `paginationChange` | `PaginationChangeEvent` | Changement de page/taille. |
51
51
  | `bulkDelete` | `any[]` | Confirmation d'une bulk action `type='delete'`. |
52
52
  | `bulkAction` | `BulkActionEvent` | Bulk action `type='custom'` (et `delete` après confirmation). |
53
53
 
54
+ ### Sélection (lecture et pilotage)
55
+
56
+ | Membre | Type | Description |
57
+ |--------|------|-------------|
58
+ | `selection` | `Signal<any[]>` | Lignes sélectionnées, **lecture seule**. |
59
+ | `selectionCount` | `Signal<number>` | Nombre de lignes sélectionnées (évite de matérialiser le tableau). |
60
+ | `selectRows(rows: any[])` | `void` | Remplace la sélection courante. Émet `selectionChange`. Les lignes sans `id` sont ignorées. |
61
+ | `clearSelection()` | `void` | Vide la sélection. Émet `selectionChange` avec `[]`. No-op si déjà vide. |
62
+
63
+ À récupérer via `viewChild` sur la table :
64
+
65
+ ```ts
66
+ readonly table = viewChild.required<TableComponent>(TableComponent);
67
+
68
+ preselect(): void {
69
+ this.table().selectRows(this.rows().filter(r => r.status === 'pending'));
70
+ }
71
+ ```
72
+
73
+ > ⚠️ **Rupture depuis beta015.** Le signal interne `selectedRows` n'est plus public. C'était
74
+ > un `WritableSignal` exposé par accident — `readonly` n'empêche que la réassignation de la
75
+ > propriété, pas les appels à `.set()` / `.update()`. Tout code qui écrivait dedans
76
+ > (`table.selectedRows.set(...)`) doit passer à `selectRows()` / `clearSelection()`, et toute
77
+ > lecture (`selectedRows().size`) à `selectionCount()` / `selection()`.
78
+
54
79
  ### Contenu projeté
55
80
 
56
81
  | Slot | Description |
@@ -198,6 +223,7 @@ rowActions: RowActionsConfig = {
198
223
  - **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.
199
224
  - **É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`.
200
225
  - **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.)
226
+ - **Cellules cliquables** : les colonnes `link`, et les `icon`/`image` avec `clickable`, sont rendues en `<button class="btn btn-link-like">` (et non en `<a href="javascript:void(0)">`, qui s'annonçait comme un lien sans naviguer). Le rendu visuel est celui du DS « Button Link Like ». Un clic émet `cellClick`.
201
227
  - **OnPush** : `data`/`columns` sont des signals → fournir des références à jour (set/update du signal).
202
228
  - **`rowActions` vs `#actionsTemplate`** : ne fournir qu'un seul. `rowActions` est l'API recommandée ; le template custom reste pour les cas hors standard.
203
229
  - **Suppression** : `type='delete'` ouvre la modale de confirmation de `basic-ui` ; n'émet `bulkDelete`/`bulkAction` qu'après confirmation.
@@ -587,6 +587,10 @@ class TableComponent {
587
587
  * toutes les lignes se retrouvent mappees sur la meme cle et la selection est cassee.
588
588
  */
589
589
  this.checkbox = input(false, ...(ngDevMode ? [{ debugName: "checkbox" }] : []));
590
+ /**
591
+ * Titre du tableau. Passe au pipe `translate` : fournir une CLE i18n, pas du texte
592
+ * en dur. Alimente le `<caption>` (lu par les lecteurs d'ecran, masque visuellement).
593
+ */
590
594
  this.title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
591
595
  this.columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
592
596
  /** Lignes du tableau. En mode `checkbox`, chaque ligne doit avoir un `id` unique (cf. `checkbox`). */
@@ -627,17 +631,27 @@ class TableComponent {
627
631
  * Selection indexee par `row.id` (et non par reference d'objet) : reste correcte
628
632
  * si le parent recree les objets `data()` au fetch (memes ids). La valeur du Map
629
633
  * conserve l'objet complet pour l'emission de `selectionChange` / bulk actions.
634
+ *
635
+ * PRIVE : auparavant expose en `selectedRows`, un signal writable public — donc
636
+ * mutable de l'exterieur via `.set()` / `.update()` (`readonly` ne protege que la
637
+ * reassignation de la propriete). La selection se pilote desormais par
638
+ * `selectRows()` / `clearSelection()`, qui emettent `selectionChange` ; la lecture
639
+ * passe par `selection()` / `selectionCount()`.
630
640
  */
631
- this.selectedRows = signal(new Map(), ...(ngDevMode ? [{ debugName: "selectedRows" }] : []));
641
+ this.selectedRowsMap = signal(new Map(), ...(ngDevMode ? [{ debugName: "selectedRowsMap" }] : []));
642
+ /** Lignes selectionnees, dans l'ordre du Map. Lecture seule. */
643
+ this.selection = computed(() => [...this.selectedRowsMap().values()], ...(ngDevMode ? [{ debugName: "selection" }] : []));
644
+ /** Nombre de lignes selectionnees — evite de materialiser le tableau pour un simple compte. */
645
+ this.selectionCount = computed(() => this.selectedRowsMap().size, ...(ngDevMode ? [{ debugName: "selectionCount" }] : []));
632
646
  /** Nombre de colonnes rendues (visibles + colonne de selection) — alimente le colspan des lignes loader/vide. */
633
647
  this.visibleColumnCount = computed(() => this.columns().filter(c => !c.hidden).length + (this.checkbox() ? 1 : 0), ...(ngDevMode ? [{ debugName: "visibleColumnCount" }] : []));
634
648
  this.allSelected = computed(() => {
635
649
  const rows = this.data();
636
- const selected = this.selectedRows();
650
+ const selected = this.selectedRowsMap();
637
651
  return rows.length > 0 && rows.every(r => selected.has(r.id));
638
652
  }, ...(ngDevMode ? [{ debugName: "allSelected" }] : []));
639
653
  this.someSelected = computed(() => {
640
- const selected = this.selectedRows();
654
+ const selected = this.selectedRowsMap();
641
655
  return this.data().some(r => selected.has(r.id)) && !this.allSelected();
642
656
  }, ...(ngDevMode ? [{ debugName: "someSelected" }] : []));
643
657
  this.defaultLabelFn = (row) => row?.name ?? row?.label ?? row?.title ?? String(row?.id ?? row);
@@ -717,17 +731,17 @@ class TableComponent {
717
731
  return value === true || value === 1 || value === '1' || value === 'true';
718
732
  }
719
733
  toggleAll() {
720
- this.selectedRows.update(current => {
734
+ this.selectedRowsMap.update(current => {
721
735
  const rows = this.data();
722
736
  const allSelected = rows.length > 0 && rows.every(r => current.has(r.id));
723
737
  return allSelected
724
738
  ? new Map()
725
739
  : new Map(rows.map(r => [r.id, r]));
726
740
  });
727
- this.selectionChange.emit([...this.selectedRows().values()]);
741
+ this.selectionChange.emit([...this.selectedRowsMap().values()]);
728
742
  }
729
743
  toggleRow(row) {
730
- this.selectedRows.update(current => {
744
+ this.selectedRowsMap.update(current => {
731
745
  const next = new Map(current);
732
746
  if (next.has(row.id)) {
733
747
  next.delete(row.id);
@@ -737,10 +751,30 @@ class TableComponent {
737
751
  }
738
752
  return next;
739
753
  });
740
- this.selectionChange.emit([...this.selectedRows().values()]);
754
+ this.selectionChange.emit([...this.selectedRowsMap().values()]);
741
755
  }
742
756
  isSelected(row) {
743
- return this.selectedRows().has(row.id);
757
+ return this.selectedRowsMap().has(row.id);
758
+ }
759
+ /**
760
+ * Remplace la selection courante par `rows` (selection programmatique : « tout
761
+ * selectionner », restauration d'un etat, pre-selection au chargement).
762
+ * Emet `selectionChange`, comme une selection a la souris.
763
+ *
764
+ * Les lignes sans `id` sont ignorees : la selection est indexee par `row.id`
765
+ * (cf. `checkbox`), les inserer mapperait toutes les lignes sur `undefined`.
766
+ */
767
+ selectRows(rows) {
768
+ const withId = (rows ?? []).filter(r => r?.id !== undefined && r?.id !== null);
769
+ this.selectedRowsMap.set(new Map(withId.map(r => [r.id, r])));
770
+ this.selectionChange.emit(this.selection());
771
+ }
772
+ /** Vide la selection. Emet `selectionChange` avec un tableau vide. */
773
+ clearSelection() {
774
+ if (this.selectedRowsMap().size === 0)
775
+ return;
776
+ this.selectedRowsMap.set(new Map());
777
+ this.selectionChange.emit([]);
744
778
  }
745
779
  resolveVariant(action) {
746
780
  if (action.variant)
@@ -754,7 +788,7 @@ class TableComponent {
754
788
  return isSignal(value) ? value() : value;
755
789
  }
756
790
  async onBulkActionClick(action) {
757
- const rows = [...this.selectedRows().values()];
791
+ const rows = [...this.selectedRowsMap().values()];
758
792
  if (action.type === 'delete') {
759
793
  const labelFn = action.itemLabel ?? this.defaultLabelFn;
760
794
  try {
@@ -847,7 +881,7 @@ class TableComponent {
847
881
  return typeof descriptor.link === 'function' ? descriptor.link(row) : descriptor.link;
848
882
  }
849
883
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
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 <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 }); }
884
+ 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() && selectionCount() > 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 {{ selectionCount() }} {{ '_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\"\n [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: (title() | translate) }\"></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 <button type=\"button\" class=\"btn btn-link-like\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </button>\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 <button type=\"button\" class=\"btn btn-link-like\" (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 </button>\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 <button type=\"button\" class=\"btn btn-link-like\" (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 </button>\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 }); }
851
885
  }
852
886
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.20", ngImport: i0, type: TableComponent, decorators: [{
853
887
  type: Component,
@@ -862,7 +896,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.20", ngImpo
862
896
  ImageComponent,
863
897
  EmptyStateComponent,
864
898
  ProgressBarComponent
865
- ], 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" }]
899
+ ], template: "@if (checkbox() && selectionCount() > 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 {{ selectionCount() }} {{ '_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\"\n [innerHTML]=\"'_COMMON._TABLE.CAPTION' | translate: { label: (title() | translate) }\"></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 <button type=\"button\" class=\"btn btn-link-like\" (click)=\"onCellClick(row, column)\">\n {{ column.translate ? (row[column.key] | translate) : row[column.key] }}\n </button>\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 <button type=\"button\" class=\"btn btn-link-like\" (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 </button>\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 <button type=\"button\" class=\"btn btn-link-like\" (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 </button>\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" }]
866
900
  }], 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 }] }] } });
867
901
 
868
902
  const RANGE_TYPES = new Set([