fold-ng 0.26.1 → 0.27.0

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/CHANGELOG.md CHANGED
@@ -8,6 +8,42 @@ All notable changes to **fold-ng** are documented here. The format follows
8
8
 
9
9
  _Nothing yet._
10
10
 
11
+ ## [0.27.0] - 2026-09-11
12
+
13
+ ### Added
14
+
15
+ - **`side="center"` — le dialogue modal, enfin, et sans second composant.**
16
+ `fold-panel-host` ne savait accoster qu'un BORD. Un « êtes-vous sûr ? », un
17
+ lecteur de code, un aperçu : ces surfaces-là n'appartiennent pas au bord de
18
+ l'écran, elles interrompent la page. `llms.txt` disait « pas encore de
19
+ dialogue modal — prenez un panneau modal » ; c'est désormais le même panneau,
20
+ avec un côté de plus.
21
+
22
+ Un composant à part aurait fait auditer deux fois la même mécanique : le
23
+ piège à focus, la barrière `inert`, le verrou de défilement, le nom
24
+ accessible, `Échap`, la poignée typée `open<TData, TResult>()`. Tout cela vit
25
+ déjà ici. Compléter l'axe coûte une valeur d'énumération ; ouvrir un second
26
+ composant coûte une seconde surface publique à tenir jusqu'à la 1.0.
27
+
28
+ 🔴 **C'est le seul côté qui QUITTE la région de contenu.** Les autres
29
+ s'ancrent en `absolute` dedans, et c'est juste : une feuille travaille à
30
+ CÔTÉ de la page, donc elle reste sous la barre de l'app et ses rails. Un
31
+ dialogue, lui, suspend la page — il est `fixed`, il couvre le chrome, et il
32
+ couvre aussi ce qu'un consommateur a lui-même épinglé par-dessus la page.
33
+ Un dock `absolute` à `z-index: 50` ne le pouvait pas : une application qui
34
+ fait monter sa propre feuille sur un téléphone passait DEVANT le panneau
35
+ censé l'interrompre.
36
+
37
+ Deux conséquences de la même idée : il porte un **scrim** — c'est la seule
38
+ forme d'ici qui obscurcit ce qu'elle suspend, là où une feuille latérale
39
+ laisse lire la page à côté — et il n'a **pas de poignée**, puisqu'il ne vient
40
+ d'aucun bord. Il arrive sur place, à peine agrandi : « ceci est maintenant
41
+ devant vous », et non « ceci a voyagé ».
42
+
43
+ ```ts
44
+ panels.open(ScanPanel, { side: "center", width: "sm" });
45
+ ```
46
+
11
47
  ## [0.26.1] - 2026-09-11
12
48
 
13
49
  ### Fixed
@@ -2531,7 +2567,8 @@ design-token stylesheet.
2531
2567
  `currentColor`; `prefers-reduced-motion` + `forced-colors` are respected;
2532
2568
  strings localise via inputs / providers (`provideFoldPanelLabels`).
2533
2569
 
2534
- [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.26.1...HEAD
2570
+ [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.27.0...HEAD
2571
+ [0.27.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.27.0
2535
2572
  [0.26.1]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.26.1
2536
2573
  [0.26.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.26.0
2537
2574
  [0.25.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.25.0
@@ -5648,9 +5648,9 @@ class FoldDataTableComponent {
5648
5648
  *
5649
5649
  * It covers **both layouts**: a wide `<tr>` and a narrow card answer the same
5650
5650
  * click, the same Enter/Space, and rove under the same arrow keys. Before
5651
- * 0.27 it reached the row only, so a table that opened a detail from
5651
+ * 0.26.1 it reached the row only, so a table that opened a detail from
5652
5652
  * `rowClick` went inert the moment its container narrowed — silently, since
5653
- * a card that ignores a tap throws nothing.
5653
+ * a card that ignores a tap throws nothing. (Fixed in 0.26.1.)
5654
5654
  */
5655
5655
  clickable = input(false, { ...(ngDevMode ? { debugName: "clickable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5656
5656
  zebra = input(false, { ...(ngDevMode ? { debugName: "zebra" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -6059,7 +6059,7 @@ class FoldDataTableComponent {
6059
6059
  }
6060
6060
  }
6061
6061
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6062
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDataTableComponent, isStandalone: true, selector: "fold-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, rowTone: { classPropertyName: "rowTone", publicName: "rowTone", isSignal: true, isRequired: false, transformFunction: null }, rowNote: { classPropertyName: "rowNote", publicName: "rowNote", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, narrowLayout: { classPropertyName: "narrowLayout", publicName: "narrowLayout", isSignal: true, isRequired: false, transformFunction: null }, cardsAt: { classPropertyName: "cardsAt", publicName: "cardsAt", isSignal: true, isRequired: false, transformFunction: null }, rowCardChrome: { classPropertyName: "rowCardChrome", publicName: "rowCardChrome", isSignal: true, isRequired: false, transformFunction: null }, mobileLayout: { classPropertyName: "mobileLayout", publicName: "mobileLayout", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyFirst: { classPropertyName: "stickyFirst", publicName: "stickyFirst", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, selectionLabel: { classPropertyName: "selectionLabel", publicName: "selectionLabel", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, toolbarSurface: { classPropertyName: "toolbarSurface", publicName: "toolbarSurface", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange", sortChange: "sortChange", rowClick: "rowClick" }, queries: [{ propertyName: "cells", predicate: FoldDataTableCellDirective, isSignal: true }, { propertyName: "rowNoteTpl", first: true, predicate: FoldDataTableRowNoteDirective, descendants: true, isSignal: true }, { propertyName: "rowDetail", first: true, predicate: FoldDataTableRowDetailDirective, descendants: true, isSignal: true }, { propertyName: "rowCard", first: true, predicate: FoldDataTableRowCardDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <!-- A card answers the pointer and the keyboard exactly as the wide\n row does \u2014 same handlers, same roving tabindex. Until 0.27 it\n answered NEITHER: `clickable` reached the <tr> only, so every\n consumer that opens a detail from `rowClick` lost its primary\n gesture the moment the viewport narrowed, and nothing failed to\n say so. A layout switch must not change what a table DOES. -->\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n <!-- \uD83D\uDD34 The note stops the click. In the wide layout it is a\n SEPARATE <tr>, so activating it never activated the row; in a\n card it lives inside the clickable shell, and without this a\n tap on the note \u2014 or on a button the consumer put there \u2014\n would also open the row. Same table, same gesture, both\n layouts. -->\n @if (hasNote(row, i)) {\n <div\n class=\"folddt-note folddt-note--card\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.clickable{cursor:pointer}.folddt-card:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldSpinnerComponent, selector: "fold-spinner", inputs: ["size", "label"] }, { kind: "component", type: FoldCheckboxComponent, selector: "fold-checkbox", inputs: ["checked", "disabled", "touched", "errors", "indeterminate", "label", "ariaLabel", "hint", "required", "size"], outputs: ["checkedChange", "touchedChange"] }] });
6062
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDataTableComponent, isStandalone: true, selector: "fold-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, rowTone: { classPropertyName: "rowTone", publicName: "rowTone", isSignal: true, isRequired: false, transformFunction: null }, rowNote: { classPropertyName: "rowNote", publicName: "rowNote", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, narrowLayout: { classPropertyName: "narrowLayout", publicName: "narrowLayout", isSignal: true, isRequired: false, transformFunction: null }, cardsAt: { classPropertyName: "cardsAt", publicName: "cardsAt", isSignal: true, isRequired: false, transformFunction: null }, rowCardChrome: { classPropertyName: "rowCardChrome", publicName: "rowCardChrome", isSignal: true, isRequired: false, transformFunction: null }, mobileLayout: { classPropertyName: "mobileLayout", publicName: "mobileLayout", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyFirst: { classPropertyName: "stickyFirst", publicName: "stickyFirst", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, selectionLabel: { classPropertyName: "selectionLabel", publicName: "selectionLabel", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, toolbarSurface: { classPropertyName: "toolbarSurface", publicName: "toolbarSurface", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange", sortChange: "sortChange", rowClick: "rowClick" }, queries: [{ propertyName: "cells", predicate: FoldDataTableCellDirective, isSignal: true }, { propertyName: "rowNoteTpl", first: true, predicate: FoldDataTableRowNoteDirective, descendants: true, isSignal: true }, { propertyName: "rowDetail", first: true, predicate: FoldDataTableRowDetailDirective, descendants: true, isSignal: true }, { propertyName: "rowCard", first: true, predicate: FoldDataTableRowCardDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <!-- A card answers the pointer and the keyboard exactly as the wide\n row does \u2014 same handlers, same roving tabindex. Until 0.26.1 it\n answered NEITHER: `clickable` reached the <tr> only, so every\n consumer that opens a detail from `rowClick` lost its primary\n gesture the moment the viewport narrowed, and nothing failed to\n say so. A layout switch must not change what a table DOES. -->\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n <!-- \uD83D\uDD34 The note stops the click. In the wide layout it is a\n SEPARATE <tr>, so activating it never activated the row; in a\n card it lives inside the clickable shell, and without this a\n tap on the note \u2014 or on a button the consumer put there \u2014\n would also open the row. Same table, same gesture, both\n layouts. -->\n @if (hasNote(row, i)) {\n <div\n class=\"folddt-note folddt-note--card\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.clickable{cursor:pointer}.folddt-card:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldSpinnerComponent, selector: "fold-spinner", inputs: ["size", "label"] }, { kind: "component", type: FoldCheckboxComponent, selector: "fold-checkbox", inputs: ["checked", "disabled", "touched", "errors", "indeterminate", "label", "ariaLabel", "hint", "required", "size"], outputs: ["checkedChange", "touchedChange"] }] });
6063
6063
  }
6064
6064
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableComponent, decorators: [{
6065
6065
  type: Component,
@@ -6069,7 +6069,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
6069
6069
  FoldIconComponent,
6070
6070
  FoldSpinnerComponent,
6071
6071
  FoldCheckboxComponent,
6072
- ], template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <!-- A card answers the pointer and the keyboard exactly as the wide\n row does \u2014 same handlers, same roving tabindex. Until 0.27 it\n answered NEITHER: `clickable` reached the <tr> only, so every\n consumer that opens a detail from `rowClick` lost its primary\n gesture the moment the viewport narrowed, and nothing failed to\n say so. A layout switch must not change what a table DOES. -->\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n <!-- \uD83D\uDD34 The note stops the click. In the wide layout it is a\n SEPARATE <tr>, so activating it never activated the row; in a\n card it lives inside the clickable shell, and without this a\n tap on the note \u2014 or on a button the consumer put there \u2014\n would also open the row. Same table, same gesture, both\n layouts. -->\n @if (hasNote(row, i)) {\n <div\n class=\"folddt-note folddt-note--card\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.clickable{cursor:pointer}.folddt-card:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"] }]
6072
+ ], template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <!-- A card answers the pointer and the keyboard exactly as the wide\n row does \u2014 same handlers, same roving tabindex. Until 0.26.1 it\n answered NEITHER: `clickable` reached the <tr> only, so every\n consumer that opens a detail from `rowClick` lost its primary\n gesture the moment the viewport narrowed, and nothing failed to\n say so. A layout switch must not change what a table DOES. -->\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n <!-- \uD83D\uDD34 The note stops the click. In the wide layout it is a\n SEPARATE <tr>, so activating it never activated the row; in a\n card it lives inside the clickable shell, and without this a\n tap on the note \u2014 or on a button the consumer put there \u2014\n would also open the row. Same table, same gesture, both\n layouts. -->\n @if (hasNote(row, i)) {\n <div\n class=\"folddt-note folddt-note--card\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.clickable{cursor:pointer}.folddt-card:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"] }]
6073
6073
  }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], rowTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowTone", required: false }] }], rowNote: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowNote", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], empty: [{ type: i0.Input, args: [{ isSignal: true, alias: "empty", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], zebra: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebra", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], narrowLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "narrowLayout", required: false }] }], cardsAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardsAt", required: false }] }], rowCardChrome: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowCardChrome", required: false }] }], mobileLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileLayout", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stickyFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyFirst", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], selectionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionLabel", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], expandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandMode", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FoldDataTableCellDirective), { isSignal: true }] }], rowNoteTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowNoteDirective), { isSignal: true }] }], rowDetail: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowDetailDirective), { isSignal: true }] }], rowCard: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowCardDirective), { isSignal: true }] }], toolbarSurface: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarSurface", required: false }] }] } });
6074
6074
 
6075
6075
  /**
@@ -14147,7 +14147,7 @@ class FoldPanelHostComponent {
14147
14147
  this.inerted = [];
14148
14148
  }
14149
14149
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPanelHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14150
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldPanelHostComponent, isStandalone: true, selector: "fold-panel-host", host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@for (panel of panels(); track panel.id) {\n <div\n class=\"panel-dock\"\n [attr.data-side]=\"panelSide(panel)\"\n [class.panel-dock--passthrough]=\"!isModal(panel)\"\n (click)=\"onBackdrop($event, panel)\"\n >\n <aside\n class=\"panel\"\n [attr.data-side]=\"panelSide(panel)\"\n [attr.data-surface]=\"panelSurface(panel)\"\n [style.--panel-width.px]=\"panel.width()\"\n role=\"dialog\"\n [attr.aria-modal]=\"isModal(panel)\"\n [attr.aria-label]=\"ariaLabel(panel)\"\n [attr.aria-labelledby]=\"ariaLabelledby(panel)\"\n tabindex=\"-1\"\n [foldFocusTrap]=\"shouldTrap(panel)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGrabber(panel)) {\n <button\n type=\"button\"\n class=\"panel-grabber\"\n [attr.aria-label]=\"dismissLabel\"\n (click)=\"onGrabber(panel)\"\n >\n <span class=\"panel-grabber__bar\" aria-hidden=\"true\"></span>\n </button>\n }\n\n @if (panel.kind === \"template\") {\n <fold-panel-header\n [title]=\"panel.title()\"\n [subtitle]=\"panel.subtitle()\"\n (closed)=\"panel.onClose()\"\n />\n <div class=\"panel-body\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n } @else {\n <ng-container [foldPanelComponentOutlet]=\"panel\" />\n }\n </aside>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.panel-dock{position:absolute;inset:0;z-index:50;display:flex;justify-content:flex-end;container-type:inline-size;overflow:clip}.panel-dock[data-side=left]{justify-content:flex-start}.panel-dock[data-side=bottom]{align-items:flex-end}.panel-dock--passthrough{pointer-events:none}.panel-dock--passthrough .panel{pointer-events:auto}.panel{--panel-width: 490px;display:flex;flex-direction:column;width:min(var(--panel-width),100%);height:100%;overflow:hidden;font-feature-settings:\"tnum\" on;background:var(--fold-color-glass);backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);-webkit-backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);border-left:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-right);animation:panel-slide-in-right .2s cubic-bezier(.4,0,.2,1)}.panel[data-side=left]{border-left:none;border-right:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-left);animation-name:panel-slide-in-left}.panel[data-side=bottom]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom}.panel-grabber{all:unset;display:none;box-sizing:border-box;width:100%;flex:none;place-items:center;padding:var(--fold-space-sm) 0;cursor:grab}.panel-grabber:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-4px}.panel-grabber__bar{display:block;width:2.25rem;height:.28rem;border-radius:var(--fold-radius-pill);background:var(--fold-color-border)}.panel[data-side=bottom] .panel-grabber{display:grid}.panel[data-surface=solid]{background:var(--fold-color-surface-card);backdrop-filter:none;-webkit-backdrop-filter:none;border-color:var(--fold-color-border)}@media(max-width:768px){.panel[data-side=right],.panel[data-side=left]{width:100vw}}@container (max-width: 640px){.panel[data-side=auto]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom;align-self:flex-end}.panel[data-side=auto] .panel-grabber{display:grid}.panel-body{padding:var(--fold-space-md)}}.panel-body{flex:1 1 auto;overflow-y:auto;padding:var(--fold-space-lg)}@keyframes panel-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panel-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes panel-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.panel{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FocusTrapDirective, selector: "[foldFocusTrap]", inputs: ["foldFocusTrap"] }, { kind: "directive", type: FoldPanelComponentOutletDirective, selector: "[foldPanelComponentOutlet]", inputs: ["foldPanelComponentOutlet"] }, { kind: "component", type: FoldPanelHeaderComponent, selector: "fold-panel-header", inputs: ["title", "subtitle", "icon", "variant", "closeLabel"], outputs: ["closed"] }] });
14150
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldPanelHostComponent, isStandalone: true, selector: "fold-panel-host", host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@for (panel of panels(); track panel.id) {\n <div\n class=\"panel-dock\"\n [attr.data-side]=\"panelSide(panel)\"\n [class.panel-dock--passthrough]=\"!isModal(panel)\"\n (click)=\"onBackdrop($event, panel)\"\n >\n <aside\n class=\"panel\"\n [attr.data-side]=\"panelSide(panel)\"\n [attr.data-surface]=\"panelSurface(panel)\"\n [style.--panel-width.px]=\"panel.width()\"\n role=\"dialog\"\n [attr.aria-modal]=\"isModal(panel)\"\n [attr.aria-label]=\"ariaLabel(panel)\"\n [attr.aria-labelledby]=\"ariaLabelledby(panel)\"\n tabindex=\"-1\"\n [foldFocusTrap]=\"shouldTrap(panel)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGrabber(panel)) {\n <button\n type=\"button\"\n class=\"panel-grabber\"\n [attr.aria-label]=\"dismissLabel\"\n (click)=\"onGrabber(panel)\"\n >\n <span class=\"panel-grabber__bar\" aria-hidden=\"true\"></span>\n </button>\n }\n\n @if (panel.kind === \"template\") {\n <fold-panel-header\n [title]=\"panel.title()\"\n [subtitle]=\"panel.subtitle()\"\n (closed)=\"panel.onClose()\"\n />\n <div class=\"panel-body\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n } @else {\n <ng-container [foldPanelComponentOutlet]=\"panel\" />\n }\n </aside>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.panel-dock{position:absolute;inset:0;z-index:50;display:flex;justify-content:flex-end;container-type:inline-size;overflow:clip}.panel-dock[data-side=left]{justify-content:flex-start}.panel-dock[data-side=bottom]{align-items:flex-end}.panel-dock[data-side=center]{position:fixed;z-index:210;display:grid;place-items:center;padding:var(--fold-space-lg);background:var(--fold-color-scrim)}.panel-dock--passthrough{pointer-events:none}.panel-dock--passthrough .panel{pointer-events:auto}.panel{--panel-width: 490px;display:flex;flex-direction:column;width:min(var(--panel-width),100%);height:100%;overflow:hidden;font-feature-settings:\"tnum\" on;background:var(--fold-color-glass);backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);-webkit-backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);border-left:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-right);animation:panel-slide-in-right .2s cubic-bezier(.4,0,.2,1)}.panel[data-side=left]{border-left:none;border-right:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-left);animation-name:panel-slide-in-left}.panel[data-side=bottom]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom}.panel[data-side=center]{width:min(var(--panel-width),100%);height:auto;max-height:min(85dvh,44rem);border:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-lg);animation-name:panel-dialog-in}.panel-grabber{all:unset;display:none;box-sizing:border-box;width:100%;flex:none;place-items:center;padding:var(--fold-space-sm) 0;cursor:grab}.panel-grabber:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-4px}.panel-grabber__bar{display:block;width:2.25rem;height:.28rem;border-radius:var(--fold-radius-pill);background:var(--fold-color-border)}.panel[data-side=bottom] .panel-grabber{display:grid}.panel[data-surface=solid]{background:var(--fold-color-surface-card);backdrop-filter:none;-webkit-backdrop-filter:none;border-color:var(--fold-color-border)}@media(max-width:768px){.panel[data-side=right],.panel[data-side=left]{width:100vw}}@container (max-width: 640px){.panel[data-side=auto]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom;align-self:flex-end}.panel[data-side=auto] .panel-grabber{display:grid}.panel-body{padding:var(--fold-space-md)}}.panel-body{flex:1 1 auto;overflow-y:auto;padding:var(--fold-space-lg)}@keyframes panel-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panel-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes panel-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes panel-dialog-in{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@media(prefers-reduced-motion:reduce){.panel{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FocusTrapDirective, selector: "[foldFocusTrap]", inputs: ["foldFocusTrap"] }, { kind: "directive", type: FoldPanelComponentOutletDirective, selector: "[foldPanelComponentOutlet]", inputs: ["foldPanelComponentOutlet"] }, { kind: "component", type: FoldPanelHeaderComponent, selector: "fold-panel-header", inputs: ["title", "subtitle", "icon", "variant", "closeLabel"], outputs: ["closed"] }] });
14151
14151
  }
14152
14152
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPanelHostComponent, decorators: [{
14153
14153
  type: Component,
@@ -14156,7 +14156,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
14156
14156
  FocusTrapDirective,
14157
14157
  FoldPanelComponentOutletDirective,
14158
14158
  FoldPanelHeaderComponent,
14159
- ], template: "@for (panel of panels(); track panel.id) {\n <div\n class=\"panel-dock\"\n [attr.data-side]=\"panelSide(panel)\"\n [class.panel-dock--passthrough]=\"!isModal(panel)\"\n (click)=\"onBackdrop($event, panel)\"\n >\n <aside\n class=\"panel\"\n [attr.data-side]=\"panelSide(panel)\"\n [attr.data-surface]=\"panelSurface(panel)\"\n [style.--panel-width.px]=\"panel.width()\"\n role=\"dialog\"\n [attr.aria-modal]=\"isModal(panel)\"\n [attr.aria-label]=\"ariaLabel(panel)\"\n [attr.aria-labelledby]=\"ariaLabelledby(panel)\"\n tabindex=\"-1\"\n [foldFocusTrap]=\"shouldTrap(panel)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGrabber(panel)) {\n <button\n type=\"button\"\n class=\"panel-grabber\"\n [attr.aria-label]=\"dismissLabel\"\n (click)=\"onGrabber(panel)\"\n >\n <span class=\"panel-grabber__bar\" aria-hidden=\"true\"></span>\n </button>\n }\n\n @if (panel.kind === \"template\") {\n <fold-panel-header\n [title]=\"panel.title()\"\n [subtitle]=\"panel.subtitle()\"\n (closed)=\"panel.onClose()\"\n />\n <div class=\"panel-body\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n } @else {\n <ng-container [foldPanelComponentOutlet]=\"panel\" />\n }\n </aside>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.panel-dock{position:absolute;inset:0;z-index:50;display:flex;justify-content:flex-end;container-type:inline-size;overflow:clip}.panel-dock[data-side=left]{justify-content:flex-start}.panel-dock[data-side=bottom]{align-items:flex-end}.panel-dock--passthrough{pointer-events:none}.panel-dock--passthrough .panel{pointer-events:auto}.panel{--panel-width: 490px;display:flex;flex-direction:column;width:min(var(--panel-width),100%);height:100%;overflow:hidden;font-feature-settings:\"tnum\" on;background:var(--fold-color-glass);backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);-webkit-backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);border-left:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-right);animation:panel-slide-in-right .2s cubic-bezier(.4,0,.2,1)}.panel[data-side=left]{border-left:none;border-right:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-left);animation-name:panel-slide-in-left}.panel[data-side=bottom]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom}.panel-grabber{all:unset;display:none;box-sizing:border-box;width:100%;flex:none;place-items:center;padding:var(--fold-space-sm) 0;cursor:grab}.panel-grabber:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-4px}.panel-grabber__bar{display:block;width:2.25rem;height:.28rem;border-radius:var(--fold-radius-pill);background:var(--fold-color-border)}.panel[data-side=bottom] .panel-grabber{display:grid}.panel[data-surface=solid]{background:var(--fold-color-surface-card);backdrop-filter:none;-webkit-backdrop-filter:none;border-color:var(--fold-color-border)}@media(max-width:768px){.panel[data-side=right],.panel[data-side=left]{width:100vw}}@container (max-width: 640px){.panel[data-side=auto]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom;align-self:flex-end}.panel[data-side=auto] .panel-grabber{display:grid}.panel-body{padding:var(--fold-space-md)}}.panel-body{flex:1 1 auto;overflow-y:auto;padding:var(--fold-space-lg)}@keyframes panel-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panel-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes panel-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.panel{animation:none}}\n"] }]
14159
+ ], template: "@for (panel of panels(); track panel.id) {\n <div\n class=\"panel-dock\"\n [attr.data-side]=\"panelSide(panel)\"\n [class.panel-dock--passthrough]=\"!isModal(panel)\"\n (click)=\"onBackdrop($event, panel)\"\n >\n <aside\n class=\"panel\"\n [attr.data-side]=\"panelSide(panel)\"\n [attr.data-surface]=\"panelSurface(panel)\"\n [style.--panel-width.px]=\"panel.width()\"\n role=\"dialog\"\n [attr.aria-modal]=\"isModal(panel)\"\n [attr.aria-label]=\"ariaLabel(panel)\"\n [attr.aria-labelledby]=\"ariaLabelledby(panel)\"\n tabindex=\"-1\"\n [foldFocusTrap]=\"shouldTrap(panel)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasGrabber(panel)) {\n <button\n type=\"button\"\n class=\"panel-grabber\"\n [attr.aria-label]=\"dismissLabel\"\n (click)=\"onGrabber(panel)\"\n >\n <span class=\"panel-grabber__bar\" aria-hidden=\"true\"></span>\n </button>\n }\n\n @if (panel.kind === \"template\") {\n <fold-panel-header\n [title]=\"panel.title()\"\n [subtitle]=\"panel.subtitle()\"\n (closed)=\"panel.onClose()\"\n />\n <div class=\"panel-body\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n } @else {\n <ng-container [foldPanelComponentOutlet]=\"panel\" />\n }\n </aside>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.panel-dock{position:absolute;inset:0;z-index:50;display:flex;justify-content:flex-end;container-type:inline-size;overflow:clip}.panel-dock[data-side=left]{justify-content:flex-start}.panel-dock[data-side=bottom]{align-items:flex-end}.panel-dock[data-side=center]{position:fixed;z-index:210;display:grid;place-items:center;padding:var(--fold-space-lg);background:var(--fold-color-scrim)}.panel-dock--passthrough{pointer-events:none}.panel-dock--passthrough .panel{pointer-events:auto}.panel{--panel-width: 490px;display:flex;flex-direction:column;width:min(var(--panel-width),100%);height:100%;overflow:hidden;font-feature-settings:\"tnum\" on;background:var(--fold-color-glass);backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);-webkit-backdrop-filter:blur(var(--fold-blur-glass)) saturate(1.5);border-left:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-right);animation:panel-slide-in-right .2s cubic-bezier(.4,0,.2,1)}.panel[data-side=left]{border-left:none;border-right:1px solid var(--fold-color-glass-border);box-shadow:var(--fold-shadow-panel-left);animation-name:panel-slide-in-left}.panel[data-side=bottom]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom}.panel[data-side=center]{width:min(var(--panel-width),100%);height:auto;max-height:min(85dvh,44rem);border:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-lg);animation-name:panel-dialog-in}.panel-grabber{all:unset;display:none;box-sizing:border-box;width:100%;flex:none;place-items:center;padding:var(--fold-space-sm) 0;cursor:grab}.panel-grabber:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-4px}.panel-grabber__bar{display:block;width:2.25rem;height:.28rem;border-radius:var(--fold-radius-pill);background:var(--fold-color-border)}.panel[data-side=bottom] .panel-grabber{display:grid}.panel[data-surface=solid]{background:var(--fold-color-surface-card);backdrop-filter:none;-webkit-backdrop-filter:none;border-color:var(--fold-color-border)}@media(max-width:768px){.panel[data-side=right],.panel[data-side=left]{width:100vw}}@container (max-width: 640px){.panel[data-side=auto]{width:100%;height:auto;max-height:min(85dvh,40rem);border-left:none;border-top:1px solid var(--fold-color-glass-border);border-radius:var(--fold-radius-lg) var(--fold-radius-lg) 0 0;box-shadow:var(--fold-shadow-lg);animation-name:panel-slide-in-bottom;align-self:flex-end}.panel[data-side=auto] .panel-grabber{display:grid}.panel-body{padding:var(--fold-space-md)}}.panel-body{flex:1 1 auto;overflow-y:auto;padding:var(--fold-space-lg)}@keyframes panel-slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panel-slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes panel-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes panel-dialog-in{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@media(prefers-reduced-motion:reduce){.panel{animation:none}}\n"] }]
14160
14160
  }], ctorParameters: () => [], propDecorators: { onEscape: [{
14161
14161
  type: HostListener,
14162
14162
  args: ["document:keydown.escape"]