@truenas/ui-components 0.3.9 → 0.3.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truenas/ui-components",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -1054,6 +1054,17 @@ declare class TnButtonComponent implements AfterViewInit {
1054
1054
  variant: _angular_core.InputSignal<"filled" | "outline">;
1055
1055
  backgroundColor: _angular_core.InputSignal<string | undefined>;
1056
1056
  label: _angular_core.InputSignal<string>;
1057
+ /**
1058
+ * Optional icon rendered alongside the label. Accepts any name resolvable by
1059
+ * `tn-icon` (sprite/registry/library). Use `iconPosition` to place it before
1060
+ * or after the label.
1061
+ */
1062
+ icon: _angular_core.InputSignal<string | undefined>;
1063
+ /**
1064
+ * Side of the label the `icon` sits on. `left` (default) renders the icon
1065
+ * before the label; `right` renders it after. No effect when `icon` is unset.
1066
+ */
1067
+ iconPosition: _angular_core.InputSignal<"left" | "right">;
1057
1068
  disabled: _angular_core.InputSignal<boolean>;
1058
1069
  /**
1059
1070
  * Native `type` of the rendered `<button>`. Defaults to `button` so stray
@@ -1099,7 +1110,7 @@ declare class TnButtonComponent implements AfterViewInit {
1099
1110
  private innerRef;
1100
1111
  ngAfterViewInit(): void;
1101
1112
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnButtonComponent, never>;
1102
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnButtonComponent, "tn-button", never, { "primary": { "alias": "primary"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "queryParams": { "alias": "queryParams"; "required": false; "isSignal": true; }; "fragment": { "alias": "fragment"; "required": false; "isSignal": true; }; "target": { "alias": "target"; "required": false; "isSignal": true; }; "rel": { "alias": "rel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "onClick": "onClick"; }, never, never, true, never>;
1113
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnButtonComponent, "tn-button", never, { "primary": { "alias": "primary"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconPosition": { "alias": "iconPosition"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "queryParams": { "alias": "queryParams"; "required": false; "isSignal": true; }; "fragment": { "alias": "fragment"; "required": false; "isSignal": true; }; "target": { "alias": "target"; "required": false; "isSignal": true; }; "rel": { "alias": "rel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "onClick": "onClick"; }, never, never, true, never>;
1103
1114
  }
1104
1115
 
1105
1116
  /**
@@ -1126,6 +1137,8 @@ declare class TnButtonHarness extends ComponentHarness {
1126
1137
  */
1127
1138
  static hostSelector: string;
1128
1139
  private _button;
1140
+ private _label;
1141
+ private _icon;
1129
1142
  /**
1130
1143
  * Gets a `HarnessPredicate` that can be used to search for a button
1131
1144
  * with specific attributes.
@@ -1156,6 +1169,27 @@ declare class TnButtonHarness extends ComponentHarness {
1156
1169
  * ```
1157
1170
  */
1158
1171
  getLabel(): Promise<string>;
1172
+ /**
1173
+ * Gets the `name` of the icon rendered inside the button, or `null` when the
1174
+ * button has no icon.
1175
+ *
1176
+ * @example
1177
+ * ```typescript
1178
+ * const saveBtn = await loader.getHarness(TnButtonHarness.with({ label: 'Save' }));
1179
+ * expect(await saveBtn.getIconName()).toBe('check');
1180
+ * ```
1181
+ */
1182
+ getIconName(): Promise<string | null>;
1183
+ /**
1184
+ * Reports whether the button renders an icon.
1185
+ *
1186
+ * @example
1187
+ * ```typescript
1188
+ * const saveBtn = await loader.getHarness(TnButtonHarness.with({ label: 'Save' }));
1189
+ * expect(await saveBtn.hasIcon()).toBe(true);
1190
+ * ```
1191
+ */
1192
+ hasIcon(): Promise<boolean>;
1159
1193
  /**
1160
1194
  * Checks whether the button is disabled.
1161
1195
  *
@@ -2756,6 +2790,17 @@ declare class TnCardComponent {
2756
2790
  protected footerActions: _angular_core.Signal<TemplateRef<any> | undefined>;
2757
2791
  title: _angular_core.InputSignal<string | undefined>;
2758
2792
  titleLink: _angular_core.InputSignal<string | undefined>;
2793
+ /**
2794
+ * Angular router commands for a title that navigates within the app. When set,
2795
+ * the title renders as an `<a [routerLink]>` so it participates in client-side
2796
+ * (SPA) routing — unlike `titleLink`, which performs a full-page
2797
+ * `window.location` navigation. Same accepted shapes as `[routerLink]`
2798
+ * (`string | unknown[]`). Takes precedence over `titleLink`.
2799
+ */
2800
+ titleRouterLink: _angular_core.InputSignal<string | unknown[] | undefined>;
2801
+ titleQueryParams: _angular_core.InputSignal<Record<string, unknown> | undefined>;
2802
+ /** Help/hover text shown on the title via the tooltip directive. */
2803
+ titleTooltip: _angular_core.InputSignal<string | undefined>;
2759
2804
  elevation: _angular_core.InputSignal<"none" | "low" | "medium" | "high">;
2760
2805
  padding: _angular_core.InputSignal<"small" | "large" | "medium">;
2761
2806
  padContent: _angular_core.InputSignal<boolean>;
@@ -2782,12 +2827,13 @@ declare class TnCardComponent {
2782
2827
  hasHeader: _angular_core.Signal<boolean>;
2783
2828
  hasHeaderRight: _angular_core.Signal<boolean>;
2784
2829
  hasFooter: _angular_core.Signal<boolean>;
2830
+ isTitleRouterLink: _angular_core.Signal<boolean>;
2785
2831
  onTitleClick(): void;
2786
2832
  onControlChange(checked: boolean): void;
2787
2833
  onHeaderMenuItemClick(_item: TnMenuItem): void;
2788
2834
  getStatusClass(type?: string): string;
2789
2835
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnCardComponent, never>;
2790
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnCardComponent, "tn-card", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "titleLink": { "alias": "titleLink"; "required": false; "isSignal": true; }; "elevation": { "alias": "elevation"; "required": false; "isSignal": true; }; "padding": { "alias": "padding"; "required": false; "isSignal": true; }; "padContent": { "alias": "padContent"; "required": false; "isSignal": true; }; "bordered": { "alias": "bordered"; "required": false; "isSignal": true; }; "background": { "alias": "background"; "required": false; "isSignal": true; }; "headerStatus": { "alias": "headerStatus"; "required": false; "isSignal": true; }; "headerControl": { "alias": "headerControl"; "required": false; "isSignal": true; }; "headerMenu": { "alias": "headerMenu"; "required": false; "isSignal": true; }; "headerMenuTriggerTestId": { "alias": "headerMenuTriggerTestId"; "required": false; "isSignal": true; }; "primaryAction": { "alias": "primaryAction"; "required": false; "isSignal": true; }; "secondaryAction": { "alias": "secondaryAction"; "required": false; "isSignal": true; }; "footerLink": { "alias": "footerLink"; "required": false; "isSignal": true; }; }, {}, ["projectedHeader", "headerActions", "footerActions"], ["[tnCardHeader]", "*"], true, never>;
2836
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnCardComponent, "tn-card", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "titleLink": { "alias": "titleLink"; "required": false; "isSignal": true; }; "titleRouterLink": { "alias": "titleRouterLink"; "required": false; "isSignal": true; }; "titleQueryParams": { "alias": "titleQueryParams"; "required": false; "isSignal": true; }; "titleTooltip": { "alias": "titleTooltip"; "required": false; "isSignal": true; }; "elevation": { "alias": "elevation"; "required": false; "isSignal": true; }; "padding": { "alias": "padding"; "required": false; "isSignal": true; }; "padContent": { "alias": "padContent"; "required": false; "isSignal": true; }; "bordered": { "alias": "bordered"; "required": false; "isSignal": true; }; "background": { "alias": "background"; "required": false; "isSignal": true; }; "headerStatus": { "alias": "headerStatus"; "required": false; "isSignal": true; }; "headerControl": { "alias": "headerControl"; "required": false; "isSignal": true; }; "headerMenu": { "alias": "headerMenu"; "required": false; "isSignal": true; }; "headerMenuTriggerTestId": { "alias": "headerMenuTriggerTestId"; "required": false; "isSignal": true; }; "primaryAction": { "alias": "primaryAction"; "required": false; "isSignal": true; }; "secondaryAction": { "alias": "secondaryAction"; "required": false; "isSignal": true; }; "footerLink": { "alias": "footerLink"; "required": false; "isSignal": true; }; }, {}, ["projectedHeader", "headerActions", "footerActions"], ["[tnCardHeader]", "*"], true, never>;
2791
2837
  }
2792
2838
 
2793
2839
  /**
@@ -5368,6 +5414,19 @@ declare class TnTableComponent<T = unknown> implements OnInit {
5368
5414
  selectable: _angular_core.InputSignal<boolean>;
5369
5415
  expandable: _angular_core.InputSignal<boolean>;
5370
5416
  bordered: _angular_core.InputSignal<boolean>;
5417
+ /**
5418
+ * Optional per-row predicate deciding whether an individual row can expand.
5419
+ * When omitted, every row is expandable (provided `expandable` is true and a
5420
+ * `tnDetailRowDef` is present). Rows for which it returns `false` render no
5421
+ * expand control, cannot be toggled, and never render a detail row. Has no
5422
+ * effect unless `expandable` is true. Re-evaluated on each change detection,
5423
+ * so it may depend on signals — keep it cheap and pure.
5424
+ *
5425
+ * If the predicate stops allowing an already-expanded row (e.g. it is driven
5426
+ * by dynamic row state), that row is pruned from the expanded set, so it will
5427
+ * not silently reappear expanded should the predicate allow it again later.
5428
+ */
5429
+ isRowExpandable: _angular_core.InputSignal<((row: T) => boolean) | undefined>;
5371
5430
  /**
5372
5431
  * Marks a single row as "active" — adds the `tn-table__row--active` class
5373
5432
  * and a left-side indicator bar. Set to `null` (default) to clear.
@@ -5434,9 +5493,15 @@ declare class TnTableComponent<T = unknown> implements OnInit {
5434
5493
  isIndeterminate: _angular_core.Signal<boolean>;
5435
5494
  trackByFn: _angular_core.Signal<(index: number, item: T) => unknown>;
5436
5495
  onSortClick(column: string): void;
5437
- getSortIcon(column: string): string;
5438
- getExpandIcon(row: T): string;
5439
5496
  isSorted(column: string): boolean;
5497
+ /**
5498
+ * Whether a specific row may currently be expanded. True when `expandable` is
5499
+ * set and — when an `isRowExpandable` predicate is provided — that predicate
5500
+ * returns true for the row. Drives the expand control's visibility and gates
5501
+ * every expansion entry point (chevron, row click, keyboard). The `__expand`
5502
+ * column and the detail row are additionally gated on `detailRowDef()`.
5503
+ */
5504
+ canExpandRow(row: T): boolean;
5440
5505
  toggleRowExpansion(row: T): void;
5441
5506
  isRowExpanded(row: T): boolean;
5442
5507
  isRowActive(row: T): boolean;
@@ -5448,7 +5513,7 @@ declare class TnTableComponent<T = unknown> implements OnInit {
5448
5513
  getColumnDef(columnName: string): TnTableColumnDirective | undefined;
5449
5514
  getCellValue(row: T, column: string): unknown;
5450
5515
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnTableComponent<any>, never>;
5451
- 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; }; "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; }; "activeRow": { "alias": "activeRow"; "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; }; }, { "sortChange": "sortChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; }, ["columnDefs", "detailRowDef"], never, true, [{ directive: typeof TnTestIdDirective; inputs: { "tnTestId": "testId"; }; outputs: {}; }]>;
5516
+ 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; }; "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; }; "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; }; }, { "sortChange": "sortChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; }, ["columnDefs", "detailRowDef"], never, true, [{ directive: typeof TnTestIdDirective; inputs: { "tnTestId": "testId"; }; outputs: {}; }]>;
5452
5517
  }
5453
5518
 
5454
5519
  /**
@@ -5566,6 +5631,14 @@ declare class TnTableHarness extends ComponentHarness {
5566
5631
  * @returns Promise resolving to true if the row has the expanded class.
5567
5632
  */
5568
5633
  isRowExpanded(rowIndex: number): Promise<boolean>;
5634
+ /**
5635
+ * Checks whether a row exposes an expand control. Returns false for rows made
5636
+ * non-expandable via the table's `isRowExpandable` predicate.
5637
+ *
5638
+ * @param rowIndex Zero-based index of the data row.
5639
+ * @returns Promise resolving to true if the row has an expand button.
5640
+ */
5641
+ hasExpandControl(rowIndex: number): Promise<boolean>;
5569
5642
  /**
5570
5643
  * Clicks a row (for tables with `clickable` enabled).
5571
5644
  *