@truenas/ui-components 0.4.12 → 0.5.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.
@@ -6321,10 +6321,51 @@ declare class TnTableColumnDirective {
6321
6321
  name: _angular_core.InputSignal<string>;
6322
6322
  sortable: _angular_core.InputSignal<boolean>;
6323
6323
  width: _angular_core.InputSignal<string | undefined>;
6324
+ /**
6325
+ * Human-readable label for the column. Used as the default header text in the
6326
+ * regular table layout AND the default field label in card mode, so a single
6327
+ * annotation serves both — prefer this over a text-only `tnHeaderCellDef`.
6328
+ * A `tnHeaderCellDef` template still overrides the header; `cardLabel` still
6329
+ * overrides the card field label. Falls back to the column `name` when unset.
6330
+ */
6331
+ label: _angular_core.InputSignal<string | undefined>;
6332
+ /**
6333
+ * Relative importance of this column in card mode (see `mobileLayout` on
6334
+ * `tn-table`). Higher numbers render first; fields ranked beyond
6335
+ * `cardPrimaryCount` fold under a "More fields" disclosure. Defaults to `0`,
6336
+ * in which case columns fall back to their `displayedColumns` order. Has no
6337
+ * effect in the regular (wide) table layout.
6338
+ */
6339
+ cardPriority: _angular_core.InputSignal<number>;
6340
+ /**
6341
+ * Marks this column as the card's title in card mode — rendered prominently
6342
+ * in the card header alongside any row actions, never as a label/value field.
6343
+ * If no column sets this, the first displayed column that isn't `cardHidden` is
6344
+ * used, falling back to the first displayed column when every column is hidden —
6345
+ * a column deliberately kept off the card is not promoted to its most prominent
6346
+ * slot.
6347
+ */
6348
+ cardTitle: _angular_core.InputSignal<boolean>;
6349
+ /**
6350
+ * When true, this column is omitted entirely from the card layout (e.g. a
6351
+ * redundant id, or a column whose meaning is already conveyed by the title).
6352
+ * Ignored in the regular table layout.
6353
+ */
6354
+ cardHidden: _angular_core.InputSignal<boolean>;
6355
+ /**
6356
+ * Overrides the field label shown for this column in card mode. Defaults to the
6357
+ * column's `label`, then to the column name.
6358
+ *
6359
+ * A `tnHeaderCellDef` template is NOT used here — it is an `ng-template`, not
6360
+ * text, so there is nothing to read out. A column whose header comes only from
6361
+ * that template renders its bare column name as the card field label; set
6362
+ * `label` (or `cardLabel`) to give the card something readable.
6363
+ */
6364
+ cardLabel: _angular_core.InputSignal<string | undefined>;
6324
6365
  headerTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
6325
6366
  cellTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
6326
6367
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnTableColumnDirective, never>;
6327
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TnTableColumnDirective, "[tnColumnDef]", ["tnColumnDef"], { "name": { "alias": "tnColumnDef"; "required": true; "isSignal": true; }; "sortable": { "alias": "sortable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; }, {}, ["headerTemplate", "cellTemplate"], never, true, never>;
6368
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TnTableColumnDirective, "[tnColumnDef]", ["tnColumnDef"], { "name": { "alias": "tnColumnDef"; "required": true; "isSignal": true; }; "sortable": { "alias": "sortable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "cardPriority": { "alias": "cardPriority"; "required": false; "isSignal": true; }; "cardTitle": { "alias": "cardTitle"; "required": false; "isSignal": true; }; "cardHidden": { "alias": "cardHidden"; "required": false; "isSignal": true; }; "cardLabel": { "alias": "cardLabel"; "required": false; "isSignal": true; }; }, {}, ["headerTemplate", "cellTemplate"], never, true, never>;
6328
6369
  }
6329
6370
  /**
6330
6371
  * Directive to define the expandable detail row template.
@@ -6345,18 +6386,80 @@ declare class TnDetailRowDefDirective {
6345
6386
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnDetailRowDefDirective, never>;
6346
6387
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TnDetailRowDefDirective, "[tnDetailRowDef]", never, {}, {}, never, never, true, never>;
6347
6388
  }
6389
+ /**
6390
+ * Directive to define a row's action controls (e.g. edit/delete buttons).
6391
+ *
6392
+ * Place inside `tn-table` to render a trailing actions column, pinned to the right edge
6393
+ * in `scroll` mode (see `mobileLayout` on `tn-table`) and scrolling with the rest of the
6394
+ * table above `cardBreakpoint`. In card mode the same template is rendered inline beside
6395
+ * the card title, so row actions stay reachable at every viewport width. The template
6396
+ * receives the row as its implicit context.
6397
+ *
6398
+ * @example
6399
+ * ```html
6400
+ * <tn-table [dataSource]="data" [displayedColumns]="columns">
6401
+ * ...column defs...
6402
+ * <ng-template tnRowActionsDef let-row>
6403
+ * <tn-icon-button name="mat-edit" ariaLabel="Edit" (click)="edit(row)" />
6404
+ * <tn-icon-button name="mat-delete" ariaLabel="Delete" (click)="remove(row)" />
6405
+ * </ng-template>
6406
+ * </tn-table>
6407
+ * ```
6408
+ */
6409
+ declare class TnRowActionsDefDirective {
6410
+ template: TemplateRef<any>;
6411
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnRowActionsDefDirective, never>;
6412
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TnRowActionsDefDirective, "[tnRowActionsDef]", never, {}, {}, never, never, true, never>;
6413
+ }
6348
6414
 
6349
6415
  interface TnTableDataSource<T = unknown> {
6350
6416
  data?: T[];
6351
6417
  connect?(): T[];
6352
6418
  disconnect?(): void;
6353
6419
  }
6420
+ /** Payload of the table's `sortChange` output. */
6354
6421
  interface TnSortEvent {
6422
+ /**
6423
+ * The column that is sorted *after* the change, or `''` when the sort was cleared — the
6424
+ * third click on a table header, or the "Unsorted" option in card mode. Both layouts
6425
+ * report the resulting state, so a cleared sort never names the column just cleared.
6426
+ */
6355
6427
  column: string;
6428
+ /** Direction after the change; `''` when no sort is active, which is always the case when `column` is `''`. */
6356
6429
  direction: 'asc' | 'desc' | '';
6357
6430
  }
6431
+ /**
6432
+ * How the table adapts when its container is narrower than `cardBreakpoint`:
6433
+ * - `scroll` — the table keeps its columns and scrolls horizontally, with the
6434
+ * first column and the actions column pinned in place *while it overflows*.
6435
+ * Default, and card mode is strictly opt-in — but note this is NOT a no-op for
6436
+ * existing tables: because the default `cardBreakpoint` is 640, any table whose
6437
+ * host content box measures under that (a phone, or a sidebar or dashboard card
6438
+ * on a desktop) gets `tn-table--scroll` and therefore the pinning, where it
6439
+ * previously scrolled all of its columns together. Raise `cardBreakpoint` if a
6440
+ * table should never pin.
6441
+ *
6442
+ * Overflow is not automatic either: `auto` layout (the default) sizes to content
6443
+ * and overflows on its own, but a `fixedLayout` table fits its container exactly,
6444
+ * so it only overflows — and only then pins — once `minColumnWidth` or `minWidth`
6445
+ * gives it a floor.
6446
+ * - `cards` — each row collapses into a stacked card (title + actions header,
6447
+ * priority-ranked label/value fields, optional detail content).
6448
+ * Above the breakpoint both modes render the regular table.
6449
+ */
6450
+ type TnTableMobileLayout = 'cards' | 'scroll';
6358
6451
  declare class TnTableComponent<T = unknown> implements OnInit {
6359
6452
  private destroyRef;
6453
+ private elementRef;
6454
+ private injector;
6455
+ /**
6456
+ * Element that had focus when `loading` went true, so it can be restored afterwards.
6457
+ *
6458
+ * `inert` blurs whatever is focused inside it and refuses focus while set, so without this
6459
+ * a keyboard user who pressed Enter on a sortable header — the flow that *starts* most
6460
+ * loads — was dropped to `<body>` and had to tab back from the top of the document.
6461
+ */
6462
+ private focusBeforeLoading;
6360
6463
  dataSource: _angular_core.InputSignal<TnTableDataSource<T> | T[]>;
6361
6464
  displayedColumns: _angular_core.InputSignal<string[]>;
6362
6465
  trackBy: _angular_core.InputSignal<((index: number, item: T) => unknown) | undefined>;
@@ -6422,6 +6525,12 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6422
6525
  * When true, shows a spinner overlay over the table. Existing rows remain
6423
6526
  * visible (dimmed) so reloads don't cause layout jumps; if there are no rows
6424
6527
  * yet, the spinner replaces the empty state.
6528
+ *
6529
+ * The rendered surfaces are `inert` while this is true, so they leave the tab order *and*
6530
+ * the accessibility tree — a screen-reader user hears the overlay's "Loading..." status
6531
+ * rather than the stale rows. That is deliberate: `pointer-events` alone left every row,
6532
+ * header and projected control activatable by keyboard against data being replaced.
6533
+ * Focus is captured on the way in and restored on the way out.
6425
6534
  */
6426
6535
  loading: _angular_core.InputSignal<boolean>;
6427
6536
  /** Accessible label announced while loading. */
@@ -6430,6 +6539,16 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6430
6539
  * When true, rows become keyboard-focusable (tabindex=0) and clicking or
6431
6540
  * pressing Enter/Space emits `rowClick`. Use this for "click row to view
6432
6541
  * details" patterns. Independent of `selectable` (checkbox) and `expandable`.
6542
+ *
6543
+ * Accessibility limitation in card mode: a card is `role="listitem"`, and the
6544
+ * roles that would announce it as activatable (`button`, `option`) have
6545
+ * presentational children, which would hide the card's own checkbox, row
6546
+ * actions and "Details" toggle from assistive tech. So a clickable card is
6547
+ * focusable and responds to Enter/Space, but is not announced as a control.
6548
+ * Active state is conveyed with `aria-current`, and expansion with
6549
+ * `aria-expanded` when `expandOnRowClick` is set. If an action must be
6550
+ * discoverable by screen-reader users, project an explicit control through
6551
+ * `[tnRowActionsDef]` rather than relying on card activation alone.
6433
6552
  */
6434
6553
  clickable: _angular_core.InputSignal<boolean>;
6435
6554
  /**
@@ -6437,6 +6556,12 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6437
6556
  * chevron. Requires `clickable` — that is what makes rows activatable at all — and `expandable`;
6438
6557
  * rows the `isRowExpandable` predicate rejects are unaffected, since `toggleRowExpansion` gates
6439
6558
  * on it. `rowClick` still emits, so a consumer can both expand and react to the click.
6559
+ *
6560
+ * Applies in card mode too, where activating the card toggles its detail section. Both controls
6561
+ * report the state: the card carries `aria-expanded` while it is the trigger (`listitem` does
6562
+ * permit it, unlike `aria-selected`), and the "Details" button carries it unconditionally,
6563
+ * because that button is what a screen-reader user reaches by tabbing. The redundancy is
6564
+ * deliberate — see the comment above the button in the template.
6440
6565
  */
6441
6566
  expandOnRowClick: _angular_core.InputSignal<boolean>;
6442
6567
  /**
@@ -6483,6 +6608,32 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6483
6608
  minWidth: _angular_core.InputSignal<string>;
6484
6609
  /** The floor actually applied to the table — explicit if given, else derived, else none. */
6485
6610
  protected readonly resolvedMinWidth: _angular_core.Signal<string | null>;
6611
+ /**
6612
+ * How the table adapts when its container is narrower than `cardBreakpoint`.
6613
+ * See {@link TnTableMobileLayout}. Defaults to `scroll`, which preserves the
6614
+ * existing horizontal-scroll behavior; set to `cards` to opt into the stacked
6615
+ * card layout.
6616
+ */
6617
+ mobileLayout: _angular_core.InputSignal<TnTableMobileLayout>;
6618
+ /**
6619
+ * Container width (px) below which `mobileLayout` takes effect. The component
6620
+ * observes its own host width (via `ResizeObserver`), so this responds to the
6621
+ * available container — a table in a narrow sidebar adapts on a wide screen.
6622
+ *
6623
+ * Measured against the host's **content box** — its border and padding are excluded — so a
6624
+ * `[bordered]` table crosses the threshold at the same content width as an unbordered one.
6625
+ */
6626
+ cardBreakpoint: _angular_core.InputSignal<number>;
6627
+ /**
6628
+ * Number of fields shown directly on each card before the rest fold under a
6629
+ * "More fields" disclosure. The title column is not counted. Defaults to `3`.
6630
+ */
6631
+ cardPrimaryCount: _angular_core.InputSignal<number>;
6632
+ /**
6633
+ * Emits the resulting sort state whenever the user changes it, from either layout.
6634
+ * Clearing a sort emits `{ column: '', direction: '' }` rather than naming the column
6635
+ * that was cleared — see {@link TnSortEvent}.
6636
+ */
6486
6637
  sortChange: _angular_core.OutputEmitterRef<TnSortEvent>;
6487
6638
  selectionChange: _angular_core.OutputEmitterRef<T[]>;
6488
6639
  /** Emits the row when a clickable row is activated (click or Enter/Space). */
@@ -6496,6 +6647,10 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6496
6647
  rowDoubleClick: _angular_core.OutputEmitterRef<T>;
6497
6648
  columnDefs: _angular_core.Signal<readonly TnTableColumnDirective[]>;
6498
6649
  detailRowDef: _angular_core.Signal<TnDetailRowDefDirective | undefined>;
6650
+ rowActionsDef: _angular_core.Signal<TnRowActionsDefDirective | undefined>;
6651
+ /** Observed host width in px; drives the switch into card mode. */
6652
+ private containerWidth;
6653
+ private resizeObserver?;
6499
6654
  /**
6500
6655
  * Sorted column and direction. Two-way bindable (`[(sortColumn)]`), so a consumer that owns the
6501
6656
  * sort — a data provider, a table destroyed and rebuilt when its list empties out — can restore
@@ -6510,14 +6665,38 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6510
6665
  * approach could address this.
6511
6666
  */
6512
6667
  expandedRows: _angular_core.WritableSignal<Set<unknown>>;
6668
+ private static instanceCount;
6669
+ private readonly instanceId;
6513
6670
  selection: SelectionModel<T>;
6514
6671
  private selectionCount;
6515
6672
  private initialized;
6516
6673
  private columnDefMap;
6517
6674
  constructor();
6675
+ /**
6676
+ * Reads the host's current **content-box** width into `containerWidth`.
6677
+ *
6678
+ * Content box specifically, to match the `ResizeObserver` callback's `contentRect`. The
6679
+ * initial read used `getBoundingClientRect()` — the border box — so the two paths measured
6680
+ * different quantities, and `[bordered]` puts a 1px border on each side: a bordered table
6681
+ * whose content box is 639px rendered as a table on first paint (641 is not < 640) and
6682
+ * flipped to cards on the observer's first callback, with no resize having happened. Host
6683
+ * padding widens the gap further.
6684
+ */
6685
+ private measureContainer;
6518
6686
  ngOnInit(): void;
6687
+ /** True when the layout should collapse rows into cards. */
6688
+ isCardMode: _angular_core.Signal<boolean>;
6689
+ /** True when the layout should keep the table but pin edge columns and scroll. */
6690
+ isScrollMode: _angular_core.Signal<boolean>;
6519
6691
  data: _angular_core.Signal<T[]>;
6520
6692
  effectiveDisplayedColumns: _angular_core.Signal<string[]>;
6693
+ /**
6694
+ * Every column the table actually renders, including the trailing actions column, which
6695
+ * `effectiveDisplayedColumns` does not track because it comes from a content template rather
6696
+ * than `displayedColumns`. Used for the detail row's `colspan`, so a detail row spans the full
6697
+ * width no matter which structural columns are on.
6698
+ */
6699
+ totalColumnCount: _angular_core.Signal<number>;
6521
6700
  isAllSelected: _angular_core.Signal<boolean>;
6522
6701
  isIndeterminate: _angular_core.Signal<boolean>;
6523
6702
  trackByFn: _angular_core.Signal<(index: number, item: T) => unknown>;
@@ -6541,17 +6720,155 @@ declare class TnTableComponent<T = unknown> implements OnInit {
6541
6720
  * {@link onRowClick} returns before toggling anything.
6542
6721
  */
6543
6722
  isRowExpandTrigger(row: T): boolean;
6723
+ /**
6724
+ * Card-mode counterpart of {@link isRowExpandTrigger}, additionally requiring a detail
6725
+ * template. Card mode renders no expansion affordance at all without one, so `aria-expanded`
6726
+ * on the card would advertise a state change that produces nothing.
6727
+ *
6728
+ * Table mode deliberately keeps the looser check: its rows are asserted to carry
6729
+ * `aria-expanded` from `expandOnRowClick` alone, and that predates this layout.
6730
+ */
6731
+ isCardExpandTrigger(row: T): boolean;
6732
+ /** DOM id for a row's detail panel, so the expand trigger can point `aria-controls` at it. */
6733
+ detailPanelId(rowIndex: number): string;
6544
6734
  isRowActive(row: T): boolean;
6545
- onRowClick(row: T): void;
6546
- onRowDoubleClick(row: T): void;
6735
+ /**
6736
+ * @param row The activated row.
6737
+ * @param event The originating DOM event, when there is one. Optional so a consumer (or a
6738
+ * test) can still activate a row programmatically; the control-target guard only applies
6739
+ * to real events, which is the only case where a projected control can be the source.
6740
+ */
6741
+ onRowClick(row: T, event?: Event): void;
6742
+ /** @param event See {@link onRowClick} — same guard, same optionality. */
6743
+ onRowDoubleClick(row: T, event?: Event): void;
6547
6744
  onRowKeydown(event: KeyboardEvent, row: T): void;
6745
+ onCardClick(event: Event, row: T): void;
6746
+ /** Card-mode counterpart of {@link onRowDoubleClick}, with the same guard. */
6747
+ onCardDoubleClick(event: Event, row: T): void;
6748
+ onCardKeydown(event: KeyboardEvent, row: T): void;
6749
+ /** Anything focusable or otherwise interactive, regardless of layout. */
6750
+ private static readonly INTERACTIVE_SELECTOR;
6751
+ /**
6752
+ * Whether an event originated on a control *within* the activation surface rather than on
6753
+ * the surface itself.
6754
+ *
6755
+ * @param event The DOM event; its `currentTarget` is the activation surface.
6756
+ * @param containerSelectors Layout-specific wrappers that count as controls.
6757
+ */
6758
+ private isControlTarget;
6759
+ /**
6760
+ * Interactive elements plus the card's own controls and its projected detail panel.
6761
+ *
6762
+ * A class allowlist is not enough: the detail panel renders consumer content inside the
6763
+ * clickable card, so an allowlist lets a click on a projected button bubble up and fire
6764
+ * `rowClick` — and with `expandOnRowClick`, collapse the very panel being used. Table mode
6765
+ * never had that problem, because there the detail row is a sibling `<tr>` outside the
6766
+ * clickable row.
6767
+ *
6768
+ * The card's own field values are deliberately not interactive, so they still activate the
6769
+ * card whether primary or folded under "More fields".
6770
+ */
6771
+ private isCardControlTarget;
6772
+ /**
6773
+ * Table-mode counterpart. The cells stop `click` themselves, but nothing stopped `keydown`,
6774
+ * so Enter on a projected action button bubbled to the row and got `preventDefault()`d —
6775
+ * which *is* how Enter activates a `<button>`, so the consumer's handler never ran and
6776
+ * `rowClick` fired for the row instead. Card mode has always guarded this; the two layouts
6777
+ * disagreed about what a projected control does under the keyboard.
6778
+ */
6779
+ private isRowControlTarget;
6780
+ /**
6781
+ * Header-cell activation, guarded like the row and the card.
6782
+ *
6783
+ * A `<th>` is an activation surface too, and a control projected through
6784
+ * `tnHeaderCellDef` broke both ways without this: clicking a filter button re-sorted the
6785
+ * table as well as running the button's own handler, and Space on a checkbox in a
6786
+ * *non-sortable* header was swallowed entirely — `onSortClick` returned early on the
6787
+ * missing `sortable()`, but the template's `preventDefault()` ran regardless, so the
6788
+ * control was simply dead.
6789
+ *
6790
+ * @param column The column the header belongs to.
6791
+ * @param event The originating DOM event.
6792
+ */
6793
+ onSortHeaderClick(column: string, event: Event): void;
6794
+ /**
6795
+ * Keyboard counterpart of {@link onSortHeaderClick}.
6796
+ *
6797
+ * Takes `Event` rather than `KeyboardEvent` because Angular types `$event` as `Event` for
6798
+ * the `keydown.enter` / `keydown.space` pseudo-events; narrowing happens here.
6799
+ */
6800
+ onSortHeaderKeydown(column: string, event: Event): void;
6801
+ /** Handles the card-mode sort `<select>` change. */
6802
+ onSortSelectChange(event: Event): void;
6548
6803
  toggleSelectAll(): void;
6549
6804
  toggleRowSelection(row: T): void;
6550
6805
  isRowSelected(row: T): boolean;
6806
+ /**
6807
+ * The column rendered as the card title. The first `displayedColumns` entry
6808
+ * whose def sets `cardTitle`, else the first column not marked `cardHidden` —
6809
+ * a column the consumer asked to keep off the card must not be promoted to its
6810
+ * most prominent slot. Falls back to the first displayed column only when every
6811
+ * column is hidden, since a card still needs a title.
6812
+ */
6813
+ cardTitleColumn: _angular_core.Signal<string>;
6814
+ /**
6815
+ * Columns rendered as label/value fields in a card, ordered by descending
6816
+ * `cardPriority` (ties keep `displayedColumns` order). Excludes the title column
6817
+ * and any `cardHidden` columns.
6818
+ */
6819
+ cardFieldColumns: _angular_core.Signal<string[]>;
6820
+ /** Fields shown directly on the card (up to `cardPrimaryCount`). */
6821
+ cardPrimaryColumns: _angular_core.Signal<string[]>;
6822
+ /** Fields tucked behind the "More fields" disclosure. */
6823
+ cardSecondaryColumns: _angular_core.Signal<string[]>;
6824
+ /**
6825
+ * Displayed columns that are sortable — populates the card-mode sort menu.
6826
+ *
6827
+ * `cardHidden` columns are excluded, because this menu *is* part of the card layout
6828
+ * and `cardHidden` promises the column is "omitted entirely" from it. Offering one
6829
+ * here would let a user reorder the cards by a value no card shows, with the
6830
+ * direction toggle giving no clue what changed — and such a column often has no
6831
+ * readable label either, since `getCardLabel()` falls back to the raw column name
6832
+ * when the header lives only in a `tnHeaderCellDef` template.
6833
+ *
6834
+ * The title column stays eligible: it is excluded from the *fields*, but it is
6835
+ * displayed, so sorting by it is meaningful.
6836
+ */
6837
+ sortableColumns: _angular_core.Signal<string[]>;
6838
+ /**
6839
+ * Whether the active sort column is one the table can actually sort by.
6840
+ *
6841
+ * `sortableColumns` rescues an active column into the menu so it stays clearable, even
6842
+ * when it is `cardHidden`, absent from `displayedColumns`, or never `sortable()`. That
6843
+ * escape hatch must not hand card mode a capability table mode refuses: clicking a
6844
+ * non-sortable header does nothing, so the direction toggle is hidden — and
6845
+ * {@link toggleSortDirection} refuses — for the same column.
6846
+ */
6847
+ protected readonly canSortActiveColumn: _angular_core.Signal<boolean>;
6848
+ /**
6849
+ * Sets (or clears, when passed `''`) the active sort column for card mode.
6850
+ * Switching columns resets to ascending, and clearing emits an empty `column` —
6851
+ * both matching {@link onSortClick}, since the same `sortChange` contract should
6852
+ * not depend on which layout the container width happens to be showing.
6853
+ */
6854
+ setSortColumn(column: string): void;
6855
+ /**
6856
+ * Flips the active sort direction between ascending and descending.
6857
+ *
6858
+ * Starts from ascending, so a column carrying an empty direction — reachable by restoring only
6859
+ * `sortColumn` through its two-way binding — sorts ascending rather than skipping straight to
6860
+ * descending. Same reading of "empty direction means not sorted" as {@link onSortClick}.
6861
+ */
6862
+ toggleSortDirection(): void;
6551
6863
  getColumnDef(columnName: string): TnTableColumnDirective | undefined;
6864
+ /**
6865
+ * Field label for a column in card mode. Precedence: `cardLabel` override →
6866
+ * shared `label` → the column name.
6867
+ */
6868
+ getCardLabel(column: string): string;
6552
6869
  getCellValue(row: T, column: string): unknown;
6553
6870
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnTableComponent<any>, never>;
6554
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnTableComponent<any>, "tn-table", never, { "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "displayedColumns": { "alias": "displayedColumns"; "required": false; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "emptyDescription": { "alias": "emptyDescription"; "required": false; "isSignal": true; }; "emptyIcon": { "alias": "emptyIcon"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "bordered": { "alias": "bordered"; "required": false; "isSignal": true; }; "isRowExpandable": { "alias": "isRowExpandable"; "required": false; "isSignal": true; }; "activeRow": { "alias": "activeRow"; "required": false; "isSignal": true; }; "activeWhen": { "alias": "activeWhen"; "required": false; "isSignal": true; }; "activeBg": { "alias": "activeBg"; "required": false; "isSignal": true; }; "activeIndicator": { "alias": "activeIndicator"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "loadingMessage": { "alias": "loadingMessage"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "expandOnRowClick": { "alias": "expandOnRowClick"; "required": false; "isSignal": true; }; "singleExpand": { "alias": "singleExpand"; "required": false; "isSignal": true; }; "fixedLayout": { "alias": "fixedLayout"; "required": false; "isSignal": true; }; "minColumnWidth": { "alias": "minColumnWidth"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "sortColumn": { "alias": "sortColumn"; "required": false; "isSignal": true; }; "sortDirection": { "alias": "sortDirection"; "required": false; "isSignal": true; }; }, { "sortChange": "sortChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; "rowDoubleClick": "rowDoubleClick"; "sortColumn": "sortColumnChange"; "sortDirection": "sortDirectionChange"; }, ["columnDefs", "detailRowDef"], never, true, [{ directive: typeof TnTestIdDirective; inputs: { "tnTestId": "testId"; }; outputs: {}; }]>;
6871
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnTableComponent<any>, "tn-table", never, { "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "displayedColumns": { "alias": "displayedColumns"; "required": false; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "emptyDescription": { "alias": "emptyDescription"; "required": false; "isSignal": true; }; "emptyIcon": { "alias": "emptyIcon"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "bordered": { "alias": "bordered"; "required": false; "isSignal": true; }; "isRowExpandable": { "alias": "isRowExpandable"; "required": false; "isSignal": true; }; "activeRow": { "alias": "activeRow"; "required": false; "isSignal": true; }; "activeWhen": { "alias": "activeWhen"; "required": false; "isSignal": true; }; "activeBg": { "alias": "activeBg"; "required": false; "isSignal": true; }; "activeIndicator": { "alias": "activeIndicator"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "loadingMessage": { "alias": "loadingMessage"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "expandOnRowClick": { "alias": "expandOnRowClick"; "required": false; "isSignal": true; }; "singleExpand": { "alias": "singleExpand"; "required": false; "isSignal": true; }; "fixedLayout": { "alias": "fixedLayout"; "required": false; "isSignal": true; }; "minColumnWidth": { "alias": "minColumnWidth"; "required": false; "isSignal": true; }; "minWidth": { "alias": "minWidth"; "required": false; "isSignal": true; }; "mobileLayout": { "alias": "mobileLayout"; "required": false; "isSignal": true; }; "cardBreakpoint": { "alias": "cardBreakpoint"; "required": false; "isSignal": true; }; "cardPrimaryCount": { "alias": "cardPrimaryCount"; "required": false; "isSignal": true; }; "sortColumn": { "alias": "sortColumn"; "required": false; "isSignal": true; }; "sortDirection": { "alias": "sortDirection"; "required": false; "isSignal": true; }; }, { "sortChange": "sortChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; "rowDoubleClick": "rowDoubleClick"; "sortColumn": "sortColumnChange"; "sortDirection": "sortDirectionChange"; }, ["columnDefs", "detailRowDef", "rowActionsDef"], never, true, [{ directive: typeof TnTestIdDirective; inputs: { "tnTestId": "testId"; }; outputs: {}; }]>;
6555
6872
  }
6556
6873
 
6557
6874
  /**
@@ -6583,13 +6900,32 @@ declare class TnTableHarness extends ComponentHarness {
6583
6900
  /**
6584
6901
  * Gets the number of data rows (excludes header and detail rows).
6585
6902
  *
6586
- * @returns Promise resolving to the row count.
6903
+ * Layout-aware: counts rendered cards in the card layout, so the count tracks what the
6904
+ * user sees rather than reporting 0 for a container that happens to be narrow.
6905
+ *
6906
+ * @returns Promise resolving to the row count, or the card count in the card layout.
6587
6907
  */
6588
6908
  getRowCount(): Promise<number>;
6909
+ /**
6910
+ * Throws when the rendered layout is `cards`, for queries that have no card equivalent.
6911
+ * The alternative is an empty array or a 0, which reads as "the table is empty" and
6912
+ * greens a test over a rendered card list — the failure mode the selection and
6913
+ * active-row methods were made layout-aware to avoid.
6914
+ */
6915
+ private assertTableLayout;
6916
+ /**
6917
+ * Mirror of {@link assertTableLayout} for the card API. `getCardCount()` answering 0 in
6918
+ * table mode is the same silent-wrong-answer shape rejected for `getRowCount()`: a spec
6919
+ * that forgot to push a sub-breakpoint width would assert emptiness and pass over 20
6920
+ * rendered rows.
6921
+ */
6922
+ private assertCardLayout;
6589
6923
  /**
6590
6924
  * Gets the text content of header cells (excludes sort icons).
6591
6925
  *
6592
6926
  * @returns Promise resolving to an array of header text strings.
6927
+ * @throws Error in the card layout, which renders no header row;
6928
+ * the thrown message names the card API.
6593
6929
  */
6594
6930
  getHeaderTexts(): Promise<string[]>;
6595
6931
  /**
@@ -6597,6 +6933,7 @@ declare class TnTableHarness extends ComponentHarness {
6597
6933
  *
6598
6934
  * @param rowIndex Zero-based index of the data row.
6599
6935
  * @returns Promise resolving to an array of cell text strings.
6936
+ * @throws Error in the card layout, which renders no rows; the thrown message names the card API.
6600
6937
  */
6601
6938
  getRowTexts(rowIndex: number): Promise<string[]>;
6602
6939
  /**
@@ -6605,18 +6942,23 @@ declare class TnTableHarness extends ComponentHarness {
6605
6942
  * @param rowIndex Zero-based index of the data row.
6606
6943
  * @param columnName The column's data-column attribute value.
6607
6944
  * @returns Promise resolving to the cell text.
6945
+ * @throws Error in the card layout, which renders no cells;
6946
+ * the thrown message names the card API.
6608
6947
  */
6609
6948
  getCellText(rowIndex: number, columnName: string): Promise<string>;
6610
6949
  /**
6611
6950
  * Gets all row texts as a 2D string array (data-column cells only).
6612
6951
  *
6613
6952
  * @returns Promise resolving to an array of row text arrays.
6953
+ * @throws Error in the card layout, which renders no rows; the thrown message names the card API.
6614
6954
  */
6615
6955
  getAllRowTexts(): Promise<string[][]>;
6616
6956
  /**
6617
6957
  * Clicks a sortable column header to cycle sort direction.
6618
6958
  *
6619
6959
  * @param columnName The column's data-column attribute value.
6960
+ * @throws Error in the card layout, which renders no column headers;
6961
+ * the thrown message names the card API.
6620
6962
  */
6621
6963
  clickSortHeader(columnName: string): Promise<void>;
6622
6964
  /**
@@ -6624,34 +6966,46 @@ declare class TnTableHarness extends ComponentHarness {
6624
6966
  *
6625
6967
  * @param columnName The column's data-column attribute value.
6626
6968
  * @returns Promise resolving to true if the column is sortable.
6969
+ * @throws Error in the card layout, which renders no column headers;
6970
+ * the thrown message names the card API.
6627
6971
  */
6628
6972
  isSortable(columnName: string): Promise<boolean>;
6629
6973
  /**
6630
6974
  * Gets the current sort direction for a column via aria-sort.
6631
6975
  *
6976
+ * `aria-sort="none"` — which a sortable-but-unsorted header now carries, so it is
6977
+ * discoverable as sortable — is normalised to null, keeping "not sorted" a single value
6978
+ * for callers. Only a non-sortable header has no attribute at all, and both answer null.
6979
+ *
6632
6980
  * @param columnName The column's data-column attribute value.
6633
6981
  * @returns Promise resolving to 'ascending', 'descending', or null.
6982
+ * @throws Error in the card layout, which renders no column headers;
6983
+ * the thrown message names the card API.
6634
6984
  */
6635
6985
  getSortDirection(columnName: string): Promise<string | null>;
6986
+ /** True when the container is narrow enough that card mode is rendered. */
6987
+ private isCards;
6636
6988
  /**
6637
- * Clicks the select-all checkbox in the header.
6989
+ * Clicks the select-all control — the header checkbox in table mode, the card
6990
+ * toolbar's "Select all" in card mode.
6638
6991
  */
6639
6992
  toggleSelectAll(): Promise<void>;
6640
6993
  /**
6641
- * Toggles selection for a specific row by clicking its checkbox cell.
6994
+ * Toggles selection for a specific row (or its card) by clicking its checkbox
6995
+ * wrapper.
6642
6996
  *
6643
6997
  * @param rowIndex Zero-based index of the data row.
6644
6998
  */
6645
6999
  toggleRowSelection(rowIndex: number): Promise<void>;
6646
7000
  /**
6647
- * Checks if a specific row's checkbox is checked.
7001
+ * Checks if a specific row (or its card) is selected.
6648
7002
  *
6649
7003
  * @param rowIndex Zero-based index of the data row.
6650
7004
  * @returns Promise resolving to true if the row's checkbox is checked.
6651
7005
  */
6652
7006
  isRowSelected(rowIndex: number): Promise<boolean>;
6653
7007
  /**
6654
- * Gets the count of currently selected rows.
7008
+ * Gets the count of currently selected rows, in either layout.
6655
7009
  *
6656
7010
  * @returns Promise resolving to the number of checked row checkboxes.
6657
7011
  */
@@ -6660,6 +7014,8 @@ declare class TnTableHarness extends ComponentHarness {
6660
7014
  * Clicks the expand button for a specific row.
6661
7015
  *
6662
7016
  * @param rowIndex Zero-based index of the data row.
7017
+ * @throws Error in the card layout — use `toggleCardDetail()`;
7018
+ * the thrown message names the card API.
6663
7019
  */
6664
7020
  toggleRowExpansion(rowIndex: number): Promise<void>;
6665
7021
  /**
@@ -6667,6 +7023,7 @@ declare class TnTableHarness extends ComponentHarness {
6667
7023
  *
6668
7024
  * @param rowIndex Zero-based index of the data row.
6669
7025
  * @returns Promise resolving to true if the row has the expanded class.
7026
+ * @throws Error in the card layout, which renders no rows; the thrown message names the card API.
6670
7027
  */
6671
7028
  isRowExpanded(rowIndex: number): Promise<boolean>;
6672
7029
  /**
@@ -6675,12 +7032,15 @@ declare class TnTableHarness extends ComponentHarness {
6675
7032
  *
6676
7033
  * @param rowIndex Zero-based index of the data row.
6677
7034
  * @returns Promise resolving to true if the row has an expand button.
7035
+ * @throws Error in the card layout, whose expand control is the card's Details button;
7036
+ * the thrown message names the card API.
6678
7037
  */
6679
7038
  hasExpandControl(rowIndex: number): Promise<boolean>;
6680
7039
  /**
6681
7040
  * Clicks a row (for tables with `clickable` enabled).
6682
7041
  *
6683
7042
  * @param rowIndex Zero-based index of the data row.
7043
+ * @throws Error in the card layout, which renders no rows; use {@link clickCard} there.
6684
7044
  */
6685
7045
  clickRow(rowIndex: number): Promise<void>;
6686
7046
  /**
@@ -6689,6 +7049,7 @@ declare class TnTableHarness extends ComponentHarness {
6689
7049
  * clicks first; this helper dispatches only the `dblclick` event.
6690
7050
  *
6691
7051
  * @param rowIndex Zero-based index of the data row.
7052
+ * @throws Error in the card layout, which renders no rows; use {@link doubleClickCard} there.
6692
7053
  */
6693
7054
  doubleClickRow(rowIndex: number): Promise<void>;
6694
7055
  /**
@@ -6696,12 +7057,14 @@ declare class TnTableHarness extends ComponentHarness {
6696
7057
  *
6697
7058
  * @param rowIndex Zero-based index of the data row.
6698
7059
  * @param key Which key to press — Enter or Space.
7060
+ * @throws Error in the card layout, which renders no rows; use {@link pressKeyOnCard} there.
6699
7061
  */
6700
7062
  pressKeyOnRow(rowIndex: number, key: 'enter' | 'space'): Promise<void>;
6701
7063
  /**
6702
7064
  * Checks if a row is keyboard-focusable (tabindex=0).
6703
7065
  *
6704
7066
  * @param rowIndex Zero-based index of the data row.
7067
+ * @throws Error in the card layout, which renders no rows; use {@link isCardFocusable} there.
6705
7068
  */
6706
7069
  isRowFocusable(rowIndex: number): Promise<boolean>;
6707
7070
  /**
@@ -6713,8 +7076,11 @@ declare class TnTableHarness extends ComponentHarness {
6713
7076
  /**
6714
7077
  * Checks if a data row is currently marked active.
6715
7078
  *
6716
- * @param rowIndex Zero-based index of the data row.
6717
- * @returns Promise resolving to true if the row has the active class.
7079
+ * Layout-aware: reads the card's active class in the card layout, which marks the same
7080
+ * state with `aria-current` rather than the row's `aria-selected`.
7081
+ *
7082
+ * @param rowIndex Zero-based index of the data row (or card).
7083
+ * @returns Promise resolving to true if the row — or card — has the active class.
6718
7084
  */
6719
7085
  isRowActive(rowIndex: number): Promise<boolean>;
6720
7086
  /**
@@ -6728,14 +7094,151 @@ declare class TnTableHarness extends ComponentHarness {
6728
7094
  *
6729
7095
  * @param detailIndex Zero-based index among currently visible detail rows.
6730
7096
  * @returns Promise resolving to the detail row text.
7097
+ * @throws Error in the card layout — use the card detail panel;
7098
+ * the thrown message names the card API.
6731
7099
  */
6732
7100
  getDetailRowContent(detailIndex: number): Promise<string>;
6733
7101
  /**
6734
7102
  * Gets the count of currently expanded detail rows.
6735
7103
  *
6736
- * @returns Promise resolving to the number of visible detail rows.
7104
+ * Layout-aware: counts open card detail panels in the card layout, which renders the same
7105
+ * expansion state without a detail `<tr>`.
7106
+ *
7107
+ * @returns Promise resolving to the number of visible detail rows, or open card detail
7108
+ * panels in the card layout.
6737
7109
  */
6738
7110
  getExpandedRowCount(): Promise<number>;
7111
+ /**
7112
+ * Reports the currently rendered layout: `cards` when the container is narrow
7113
+ * enough that `mobileLayout="cards"` has taken effect, otherwise `table`.
7114
+ *
7115
+ * @returns Promise resolving to 'cards' or 'table'.
7116
+ */
7117
+ getLayoutMode(): Promise<'cards' | 'table'>;
7118
+ /**
7119
+ * Gets the number of rendered cards (card layout only).
7120
+ *
7121
+ * @returns Promise resolving to the card count.
7122
+ */
7123
+ getCardCount(): Promise<number>;
7124
+ /**
7125
+ * Gets the title text of a card.
7126
+ *
7127
+ * @param cardIndex Zero-based index of the card.
7128
+ * @returns Promise resolving to the card title text.
7129
+ */
7130
+ getCardTitle(cardIndex: number): Promise<string>;
7131
+ /**
7132
+ * Gets the value text of a field within a card, by column name. The field
7133
+ * may be a primary field or one tucked under "More fields".
7134
+ *
7135
+ * @param cardIndex Zero-based index of the card.
7136
+ * @param columnName The column's data-column attribute value.
7137
+ * @returns Promise resolving to the field's value text.
7138
+ */
7139
+ getCardFieldValue(cardIndex: number, columnName: string): Promise<string>;
7140
+ /**
7141
+ * Gets the column names of the fields shown directly on a card (i.e. not
7142
+ * those hidden behind the "More fields" disclosure).
7143
+ *
7144
+ * @param cardIndex Zero-based index of the card.
7145
+ * @returns Promise resolving to an array of column names.
7146
+ */
7147
+ getCardPrimaryFieldColumns(cardIndex: number): Promise<string[]>;
7148
+ /**
7149
+ * Expands the "More fields" disclosure on a card to reveal lower-priority
7150
+ * fields. No-op if the card has no secondary fields.
7151
+ *
7152
+ * @param cardIndex Zero-based index of the card.
7153
+ */
7154
+ expandCardMoreFields(cardIndex: number): Promise<void>;
7155
+ /**
7156
+ * Toggles a card's detail section (card layout equivalent of row expansion).
7157
+ *
7158
+ * @param cardIndex Zero-based index of the card.
7159
+ */
7160
+ toggleCardDetail(cardIndex: number): Promise<void>;
7161
+ /**
7162
+ * Gets the currently selected sort column in the card-layout sort menu, or
7163
+ * `''` when unsorted. Returns null if the sort menu isn't rendered.
7164
+ *
7165
+ * @returns Promise resolving to the selected column name, '', or null.
7166
+ */
7167
+ getCardSortColumn(): Promise<string | null>;
7168
+ /**
7169
+ * Gets the active sort direction in the card layout, read from the direction toggle's
7170
+ * `data-sort-direction`. Deliberately not derived from the button's `aria-label`: matching
7171
+ * display text would silently report one direction forever if the wording or locale changed.
7172
+ *
7173
+ * @returns Promise resolving to 'asc' or 'desc'; `''` both when sorted by nothing and when the
7174
+ * active column isn't sortable (the toggle isn't rendered in either case, and this reads the
7175
+ * rendered control — so a non-sortable active column reports `''` even though the component's
7176
+ * `sortDirection()` holds a value); or null when the card sort menu isn't rendered at all
7177
+ * (table layout, or no sortable columns) — the same null-vs-empty distinction
7178
+ * {@link getCardSortColumn} makes.
7179
+ */
7180
+ getCardSortDirection(): Promise<'asc' | 'desc' | '' | null>;
7181
+ /**
7182
+ * Clicks the sort-direction toggle in the card-layout sort menu. No-op when the toggle
7183
+ * isn't rendered, which is three cases: the table layout is showing (the whole card sort
7184
+ * menu is absent — so a call made before the container narrowed does nothing and reports
7185
+ * success), no active sort column, or an active column that isn't `sortable()` — card mode
7186
+ * deliberately declines to reorder by a column whose table header ignores clicks.
7187
+ */
7188
+ toggleCardSortDirection(): Promise<void>;
7189
+ /**
7190
+ * Clicks a card body (card mirror of {@link clickRow}, for tables with `clickable`).
7191
+ *
7192
+ * Targets the card's title rather than the card box, because the card box's centre can sit
7193
+ * on a projected row action or the selection checkbox, and the activation guard ignores
7194
+ * clicks that originate on a control — the click would land and nothing would happen.
7195
+ *
7196
+ * @param cardIndex Zero-based index of the card.
7197
+ * @throws Error in the table layout; use {@link clickRow} there.
7198
+ */
7199
+ clickCard(cardIndex: number): Promise<void>;
7200
+ /**
7201
+ * Double-clicks a card, triggering `rowDoubleClick` (card mirror of
7202
+ * {@link doubleClickRow}). As there, only the `dblclick` event is dispatched — a real
7203
+ * double-click also fires two single clicks first.
7204
+ *
7205
+ * Dispatched on the card rather than on the title {@link clickCard} aims at, because a
7206
+ * synthesised event does not bubble: sent to the title it would never reach the card's
7207
+ * handler. There is no cost to it here — the target is set explicitly, so unlike a real
7208
+ * pointer click it cannot land on a projected control.
7209
+ *
7210
+ * @param cardIndex Zero-based index of the card.
7211
+ * @throws Error in the table layout; use {@link doubleClickRow} there.
7212
+ */
7213
+ doubleClickCard(cardIndex: number): Promise<void>;
7214
+ /**
7215
+ * Sends a keyboard event to a card (Enter/Space activate clickable cards). Card mirror of
7216
+ * {@link pressKeyOnRow}; the key goes to the card itself, which is the element that carries
7217
+ * `tabindex` and the keydown handler.
7218
+ *
7219
+ * @param cardIndex Zero-based index of the card.
7220
+ * @param key Which key to press — Enter or Space.
7221
+ * @throws Error in the table layout; use {@link pressKeyOnRow} there.
7222
+ */
7223
+ pressKeyOnCard(cardIndex: number, key: 'enter' | 'space'): Promise<void>;
7224
+ /**
7225
+ * Checks if a card is keyboard-focusable (tabindex=0). Card mirror of
7226
+ * {@link isRowFocusable}.
7227
+ *
7228
+ * @param cardIndex Zero-based index of the card.
7229
+ * @throws Error in the table layout; use {@link isRowFocusable} there.
7230
+ */
7231
+ isCardFocusable(cardIndex: number): Promise<boolean>;
7232
+ /** The card box itself — the element carrying `tabindex`, the handlers and the ARIA state. */
7233
+ private cardAt;
7234
+ /** The surface pointer activation is aimed at — see {@link clickCard} for why not the card. */
7235
+ private cardActivationTarget;
7236
+ /**
7237
+ * Bounds check for the layout-aware methods. Counts whatever the rendered layout shows, via
7238
+ * `getRowCount()` — unlike {@link assertRowExists}, which deliberately counts rows only,
7239
+ * because its callers refuse card mode outright.
7240
+ */
7241
+ private assertIndexExists;
6739
7242
  private assertRowExists;
6740
7243
  }
6741
7244
  /**
@@ -6744,6 +7247,47 @@ declare class TnTableHarness extends ComponentHarness {
6744
7247
  interface TnTableHarnessFilters extends BaseHarnessFilters {
6745
7248
  }
6746
7249
 
7250
+ /**
7251
+ * Testing utilities for `tn-table`'s container-driven responsive layout.
7252
+ *
7253
+ * Part of the public API because `TnTableHarness`'s layout-mismatch messages tell the caller
7254
+ * to widen or narrow the container past `cardBreakpoint`, and jsdom implements no
7255
+ * `ResizeObserver` — so without a stand-in a consumer's own spec has no supported way to
7256
+ * follow that advice.
7257
+ *
7258
+ * Namespaced rather than exported as loose functions, matching `TnIconTesting` and
7259
+ * `TnToastTesting`: these names live at the top level of the package, and `installObserver`
7260
+ * or `emitContainerWidth` on their own give no hint that they concern tables.
7261
+ *
7262
+ * @example
7263
+ * ```typescript
7264
+ * let restoreResizeObserver: () => void;
7265
+ *
7266
+ * beforeEach(() => { restoreResizeObserver = TnTableTesting.installResizeObserver(); });
7267
+ * afterEach(() => { restoreResizeObserver(); });
7268
+ *
7269
+ * // ...then, inside a test:
7270
+ * TnTableTesting.emitContainerWidth(320);
7271
+ * fixture.detectChanges();
7272
+ * ```
7273
+ */
7274
+ declare const TnTableTesting: {
7275
+ /**
7276
+ * Swaps `globalThis.ResizeObserver` for a stand-in and clears any instances left by a
7277
+ * previous test.
7278
+ *
7279
+ * @returns A function that restores the original global — call it in `afterEach`.
7280
+ */
7281
+ installResizeObserver(): () => void;
7282
+ /**
7283
+ * Pushes `width` through every observer the component under test registered, as its
7284
+ * content-box width — the same quantity `measureContainer` reads on the initial pass.
7285
+ *
7286
+ * @param width Content-box width in px. A 0 reads as unmeasurable, not narrow.
7287
+ */
7288
+ emitContainerWidth(width: number): void;
7289
+ };
7290
+
6747
7291
  /**
6748
7292
  * Default labels rendered inside `tn-table-pager`. Consumers can override any
6749
7293
  * subset of these at the app root by providing a value for the
@@ -11394,5 +11938,5 @@ declare const TN_THEME_DEFINITIONS: readonly TnThemeDefinition[];
11394
11938
  */
11395
11939
  declare const THEME_MAP: Map<TnTheme, TnThemeDefinition>;
11396
11940
 
11397
- export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, THEME_MAP, THEME_STORAGE_KEY, TN_CALENDAR_INTL, TN_CALENDAR_INTL_DEFAULTS, TN_FORM_FIELD_CONTEXT, TN_FORM_FIELD_ERRORS, TN_RADIO_GROUP, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarCellHarness, TnCalendarComponent, TnCalendarHarness, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerHarness, TnFilePickerPopupComponent, TnFormFieldComponent, TnFormFieldHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeDataSource, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioGroupComponent, TnRadioGroupHarness, TnRadioHarness, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnStepperHarness, TnStepperNextDirective, TnStepperPreviousDirective, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeHarness, TnTreeNodeComponent, TnTreeNodeHarness, TnTreeNodeOutletDirective, TnTreeVirtualScrollNodeOutletDirective, TnTreeVirtualScrollViewComponent, TnTreeVirtualScrollViewHarness, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, allowsCurrentDirectorySelection, composeTestId, controlTestId, createFlatTreeControl, createLucideLibrary, createNestedTreeControl, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, defaultTreeItemSize, formatSize, getSelectableTypes, injectTnCalendarIntl, injectTnFormFieldAria, isPathWithinRoot, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, normalizeRootPath, optionTestId, parseLabelMarkup, parseSize, registerLucideIcons, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
11398
- export type { AutocompleteHarnessFilters, BannerHarnessFilters, ButtonHarnessFilters, ButtonToggleHarnessFilters, CalendarCell, CalendarCellFill, CalendarCellHarnessFilters, CalendarHarnessFilters, CheckboxHarnessFilters, ChipColor, ChipHarnessFilters, DateInputHarnessFilters, DateRange, DateRangeInputHarnessFilters, DialogHarnessFilters, EmptyHarnessFilters, ExpansionPanelHarnessFilters, FileInputHarnessFilters, FilePickerCallbacks, FilePickerCreateAction, FilePickerCreateActionEvent, FilePickerError, FilePickerHarnessFilters, FilePickerMode, FileSystemItem, FileSystemItemType, FlatTreeControlOptions, FormFieldHarnessFilters, FormSectionHarnessFilters, IconButtonHarnessFilters, IconHarnessFilters, IconLibrary, IconLibraryType, IconResult, IconSize, IconSource, IconTestingMockOverrides, InputHarnessFilters, KeyCombination, LabelMarkupSegment, LabelMarkupSegmentType, LabelType, LucideIconOptions, MenuHarnessFilters, MockIconRegistry, MockSpriteLoader, NestedTreeControlOptions, PathSegment, PlatformType, ProgressBarMode, RadioGroupHarnessFilters, RadioHarnessFilters, ResolvedIcon, SelectHarnessFilters, ShortcutHandler, SidePanelHarnessFilters, SizeStandard, SlideToggleColor, SlideToggleHarnessFilters, SpinnerMode, SpriteConfig, StepperHarnessFilters, SubscriptSizing, TabChangeEvent, TabHarnessFilters, TabPanelHarnessFilters, TabsHarnessFilters, TnAutocompleteOption, TnBannerType, TnButtonToggleType, TnCalendarIntl, TnCalendarIntlInput, TnCalendarView, TnCardAction, TnCardControl, TnCardFooterLink, TnCardHeaderStatus, TnChipInputHarnessFilters, TnChipInputOption, TnConfirmDialogData, TnDialogDefaults, TnDialogOpenTarget, TnDrawerMode, TnDrawerPosition, TnEmptySize, TnFlatTreeNode, TnFormFieldAriaBindings, TnFormFieldContext, TnFormFieldErrorMessage, TnFormFieldErrorMessages, TnFormFieldErrorResolver, TnMenuItem, TnOptionTestIdSource, TnRadioGroupApi, TnRadioOption, TnSelectOption, TnSelectOptionGroup, TnSelectionChange, TnSortEvent, TnTableDataProvider, TnTableDataSource, TnTableHarnessFilters, TnTablePagerHarnessFilters, TnTablePagerLabels, TnTablePagination, TnTestAttrName, TnTestIdValue, TnThemeDefinition, TnToastCall, TnToastConfig, TnTreeExpansion, TnTreeHarnessFilters, TnTreeNodeHarnessFilters, TnTreeVirtualNodeData, TnTreeVirtualScrollViewHarnessFilters, TooltipPosition, YearCell };
11941
+ export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, THEME_MAP, THEME_STORAGE_KEY, TN_CALENDAR_INTL, TN_CALENDAR_INTL_DEFAULTS, TN_FORM_FIELD_CONTEXT, TN_FORM_FIELD_ERRORS, TN_RADIO_GROUP, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarCellHarness, TnCalendarComponent, TnCalendarHarness, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerHarness, TnFilePickerPopupComponent, TnFormFieldComponent, TnFormFieldHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeDataSource, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioGroupComponent, TnRadioGroupHarness, TnRadioHarness, TnRowActionsDefDirective, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnStepperHarness, TnStepperNextDirective, TnStepperPreviousDirective, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTableTesting, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeHarness, TnTreeNodeComponent, TnTreeNodeHarness, TnTreeNodeOutletDirective, TnTreeVirtualScrollNodeOutletDirective, TnTreeVirtualScrollViewComponent, TnTreeVirtualScrollViewHarness, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, allowsCurrentDirectorySelection, composeTestId, controlTestId, createFlatTreeControl, createLucideLibrary, createNestedTreeControl, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, defaultTreeItemSize, formatSize, getSelectableTypes, injectTnCalendarIntl, injectTnFormFieldAria, isPathWithinRoot, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, normalizeRootPath, optionTestId, parseLabelMarkup, parseSize, registerLucideIcons, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
11942
+ export type { AutocompleteHarnessFilters, BannerHarnessFilters, ButtonHarnessFilters, ButtonToggleHarnessFilters, CalendarCell, CalendarCellFill, CalendarCellHarnessFilters, CalendarHarnessFilters, CheckboxHarnessFilters, ChipColor, ChipHarnessFilters, DateInputHarnessFilters, DateRange, DateRangeInputHarnessFilters, DialogHarnessFilters, EmptyHarnessFilters, ExpansionPanelHarnessFilters, FileInputHarnessFilters, FilePickerCallbacks, FilePickerCreateAction, FilePickerCreateActionEvent, FilePickerError, FilePickerHarnessFilters, FilePickerMode, FileSystemItem, FileSystemItemType, FlatTreeControlOptions, FormFieldHarnessFilters, FormSectionHarnessFilters, IconButtonHarnessFilters, IconHarnessFilters, IconLibrary, IconLibraryType, IconResult, IconSize, IconSource, IconTestingMockOverrides, InputHarnessFilters, KeyCombination, LabelMarkupSegment, LabelMarkupSegmentType, LabelType, LucideIconOptions, MenuHarnessFilters, MockIconRegistry, MockSpriteLoader, NestedTreeControlOptions, PathSegment, PlatformType, ProgressBarMode, RadioGroupHarnessFilters, RadioHarnessFilters, ResolvedIcon, SelectHarnessFilters, ShortcutHandler, SidePanelHarnessFilters, SizeStandard, SlideToggleColor, SlideToggleHarnessFilters, SpinnerMode, SpriteConfig, StepperHarnessFilters, SubscriptSizing, TabChangeEvent, TabHarnessFilters, TabPanelHarnessFilters, TabsHarnessFilters, TnAutocompleteOption, TnBannerType, TnButtonToggleType, TnCalendarIntl, TnCalendarIntlInput, TnCalendarView, TnCardAction, TnCardControl, TnCardFooterLink, TnCardHeaderStatus, TnChipInputHarnessFilters, TnChipInputOption, TnConfirmDialogData, TnDialogDefaults, TnDialogOpenTarget, TnDrawerMode, TnDrawerPosition, TnEmptySize, TnFlatTreeNode, TnFormFieldAriaBindings, TnFormFieldContext, TnFormFieldErrorMessage, TnFormFieldErrorMessages, TnFormFieldErrorResolver, TnMenuItem, TnOptionTestIdSource, TnRadioGroupApi, TnRadioOption, TnSelectOption, TnSelectOptionGroup, TnSelectionChange, TnSortEvent, TnTableDataProvider, TnTableDataSource, TnTableHarnessFilters, TnTableMobileLayout, TnTablePagerHarnessFilters, TnTablePagerLabels, TnTablePagination, TnTestAttrName, TnTestIdValue, TnThemeDefinition, TnToastCall, TnToastConfig, TnTreeExpansion, TnTreeHarnessFilters, TnTreeNodeHarnessFilters, TnTreeVirtualNodeData, TnTreeVirtualScrollViewHarnessFilters, TooltipPosition, YearCell };