@truenas/ui-components 0.8.12 → 0.8.14

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.8.12",
3
+ "version": "0.8.14",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -11591,6 +11591,11 @@ export declare class TnTableComponent<T = unknown> implements OnInit {
11591
11591
  * <!-- <tr data-testid="row-jane-doe"> -->
11592
11592
  * ```
11593
11593
  *
11594
+ * The controls the table draws for the row are derived from the same base, in both layouts:
11595
+ * `checkbox-select-<base>` on its selection checkbox and `button-expand-<base>` on its expand
11596
+ * chevron or Details toggle. The select-all is `checkbox-all-rows` with or without this input —
11597
+ * deliberately outside `checkbox-select-*`, so no row base (not even `all`) can produce it.
11598
+ *
11594
11599
  * Cells are not covered by this: a suite that has to read one cell of a row still needs an id
11595
11600
  * on the element that cell renders. Tagging the row is what makes the row itself reachable —
11596
11601
  * which is the part a consumer cannot add from the outside.
@@ -11881,6 +11886,18 @@ export declare class TnTableComponent<T = unknown> implements OnInit {
11881
11886
  * identical between passes, and correct after a reload hands back new row objects.
11882
11887
  */
11883
11888
  protected readonly rowTestIds: Signal<TnTestIdValue[]>;
11889
+ /**
11890
+ * Base for each row's selection checkbox, `['select', ...row base]` — so a row tagged
11891
+ * `row-job-42` gets `checkbox-select-job-42`. Role leads, as in `tn-dialog-shell`'s chrome.
11892
+ *
11893
+ * The same array serves table and card mode, so a narrow viewport does not rename a row's
11894
+ * controls any more than it renames the row. Without a usable row base the entry is
11895
+ * `undefined` rather than `['select']`, which would give every row the same `checkbox-select`.
11896
+ */
11897
+ protected readonly rowSelectTestIds: Signal<TnTestIdValue[]>;
11898
+ /** Base for each row's expand control — the table-mode chevron and the card's Details toggle. */
11899
+ protected readonly rowExpandTestIds: Signal<TnTestIdValue[]>;
11900
+ private rowControlTestIds;
11884
11901
  effectiveDisplayedColumns: Signal<string[]>;
11885
11902
  /**
11886
11903
  * Every column the table actually renders, including the trailing actions column, which
@@ -18240,6 +18257,22 @@ export interface FilePickerCreateActionEvent {
18240
18257
  /** Directory being browsed when the action was triggered. */
18241
18258
  parentPath: string;
18242
18259
  }
18260
+ /**
18261
+ * Payload of `itemSelectionChange`: the committed value together with the
18262
+ * listed items it refers to, for consumers that need more than the path
18263
+ * (e.g. to require that a FILE was picked).
18264
+ */
18265
+ export interface FilePickerSelection {
18266
+ /** The committed value — the same payload `selectionChange` carries. */
18267
+ value: string | string[];
18268
+ /**
18269
+ * One entry per selected path, in value order. `null` when the picker has
18270
+ * not listed that path in this session — e.g. a typed path the user never
18271
+ * browsed to, or the browsed directory itself submitted on an empty
18272
+ * selection before its parent was listed. Empty for a cleared selection.
18273
+ */
18274
+ items: (FileSystemItem | null)[];
18275
+ }
18243
18276
  export interface FilePickerError {
18244
18277
  type: 'navigation' | 'permission' | 'creation' | 'validation';
18245
18278
  message: string;
@@ -18264,6 +18297,24 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18264
18297
  /** Consumer-defined creation flows shown as buttons in the popup footer. */
18265
18298
  createActions: import("@angular/core").InputSignal<FilePickerCreateAction[]>;
18266
18299
  allowManualInput: import("@angular/core").InputSignal<boolean>;
18300
+ /**
18301
+ * Commit typed input verbatim instead of treating it as a path to validate:
18302
+ * no `rootPath` confinement, no `callbacks.validatePath`, no `valueRoot`
18303
+ * mapping — the text the user typed is the value. Lets a field accept
18304
+ * entries the browser cannot list, e.g. `EXTERNAL:192.168.0.200\SHARE` or
18305
+ * a dataset name for a pool that is not imported. With `multiSelect`, the
18306
+ * text is split on commas into one entry per comma-separated part (trimmed,
18307
+ * empty parts dropped), so commas cannot appear inside an entry. Committing
18308
+ * closes the popup. Popup selections are unaffected. Requires
18309
+ * `allowManualInput`.
18310
+ */
18311
+ allowFreeText: import("@angular/core").InputSignal<boolean>;
18312
+ /**
18313
+ * Explicit accessible name for the path input. Inside a `tn-form-field` the
18314
+ * input is named by the field label automatically (via `aria-labelledby`),
18315
+ * so leave this unset there unless the field has no visible label.
18316
+ */
18317
+ ariaLabel: import("@angular/core").InputSignal<string | undefined>;
18267
18318
  /**
18268
18319
  * Open the picker popup when the input is clicked while no path is selected
18269
18320
  * yet — an empty field means the user is about to pick something, so the
@@ -18302,6 +18353,11 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18302
18353
  fileExtensions: import("@angular/core").InputSignal<string[] | undefined>;
18303
18354
  callbacks: import("@angular/core").InputSignal<FilePickerCallbacks | undefined>;
18304
18355
  selectionChange: import("@angular/core").OutputEmitterRef<string | string[]>;
18356
+ /**
18357
+ * Emitted alongside every `selectionChange` with the listed
18358
+ * `FileSystemItem` behind each selected path (or `null` when unknown).
18359
+ */
18360
+ itemSelectionChange: import("@angular/core").OutputEmitterRef<FilePickerSelection>;
18305
18361
  pathChange: import("@angular/core").OutputEmitterRef<string>;
18306
18362
  /** Re-emitted from the popup when one of the `createActions` buttons is pressed. */
18307
18363
  createAction: import("@angular/core").OutputEmitterRef<FilePickerCreateActionEvent>;
@@ -18319,6 +18375,20 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18319
18375
  loading: import("@angular/core").WritableSignal<boolean>;
18320
18376
  hasError: import("@angular/core").WritableSignal<boolean>;
18321
18377
  private formDisabled;
18378
+ /**
18379
+ * Field-derived ARIA for the path input when projected into a
18380
+ * `tn-form-field` (label, description, invalid, required). All-null when
18381
+ * standalone or when `ariaLabel` overrides.
18382
+ */
18383
+ protected readonly fieldAria: import("@truenas/ui-components").TnFormFieldAriaBindings;
18384
+ /**
18385
+ * Every item the picker has listed, by absolute path, so a selection can be
18386
+ * resolved back to its item even after browsing elsewhere (multi-select
18387
+ * across directories, `selectPath`, typed paths). Kept for the picker's
18388
+ * lifetime: a stale entry only means a stale `type` for a path that changed
18389
+ * on disk after it was listed.
18390
+ */
18391
+ private listedItems;
18322
18392
  isDisabled: import("@angular/core").Signal<boolean>;
18323
18393
  /** Explicit `testId` wins; otherwise the bound control's name (formControlName etc.). */
18324
18394
  protected resolvedTestId: import("@angular/core").Signal<TnTestIdValue>;
@@ -18348,6 +18418,14 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18348
18418
  * and spam `validatePath` with paths the user never meant.
18349
18419
  */
18350
18420
  onPathCommit(event: Event): void;
18421
+ /**
18422
+ * `allowFreeText` commit: the typed text is the value, verbatim (single
18423
+ * mode keeps even surrounding whitespace, as the field shows it), and a
18424
+ * field holding only whitespace clears the selection like an empty one.
18425
+ * Selection state still tracks the absolute form of each trimmed entry (the
18426
+ * same mapping `writeValue` applies) so reopening the popup reflects it.
18427
+ */
18428
+ private commitFreeText;
18351
18429
  /** `openOnClick` entry point. */
18352
18430
  onInputClick(): void;
18353
18431
  /**
@@ -18429,6 +18507,14 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18429
18507
  * would be the surprising behavior.
18430
18508
  */
18431
18509
  private updateSelection;
18510
+ /**
18511
+ * Emits `selectionChange` and `itemSelectionChange` for a committed value.
18512
+ * Items are looked up by the absolute form of each trimmed entry, which is
18513
+ * how listings are indexed — a free-text value keeps any surrounding
18514
+ * whitespace the user typed, but still resolves to the item it names.
18515
+ */
18516
+ private emitSelection;
18517
+ private indexListedItems;
18432
18518
  private normalizedValueRoot;
18433
18519
  /** Maps an internal absolute path into the `valueRoot`-relative value space. */
18434
18520
  private toValueSpace;
@@ -18458,6 +18544,16 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18458
18544
  "required": false;
18459
18545
  "isSignal": true;
18460
18546
  };
18547
+ "allowFreeText": {
18548
+ "alias": "allowFreeText";
18549
+ "required": false;
18550
+ "isSignal": true;
18551
+ };
18552
+ "ariaLabel": {
18553
+ "alias": "ariaLabel";
18554
+ "required": false;
18555
+ "isSignal": true;
18556
+ };
18461
18557
  "openOnClick": {
18462
18558
  "alias": "openOnClick";
18463
18559
  "required": false;
@@ -18505,6 +18601,7 @@ export declare class TnFilePickerComponent implements ControlValueAccessor, OnIn
18505
18601
  };
18506
18602
  }, {
18507
18603
  "selectionChange": "selectionChange";
18604
+ "itemSelectionChange": "itemSelectionChange";
18508
18605
  "pathChange": "pathChange";
18509
18606
  "createAction": "createAction";
18510
18607
  "error": "error";
@@ -18588,31 +18685,35 @@ export declare class TnFilePickerHarness extends ComponentHarness {
18588
18685
  */
18589
18686
  getValue(): Promise<string>;
18590
18687
  /**
18591
- * Sets the picker's value by typing a single path into the path input and
18592
- * committing it via the input's `change` event, exactly as a user pressing
18593
- * Enter would.
18688
+ * Sets the picker's value by typing into the path input and committing it
18689
+ * via the input's `change` event, exactly as a user pressing Enter would.
18594
18690
  *
18595
- * Unlike `IxExplorerHarness.setValue` there is no `string[]` overload:
18596
- * tn-file-picker treats typed input as ONE path even in multi-select mode
18597
- * (commas are legal in paths, so they are never list separators). In
18598
- * multi-select, committing a typed path REPLACES the whole selection with
18599
- * that single path; build a real multi-selection through the popup with
18600
- * {@link clickItem} + {@link clickSelect}.
18691
+ * By default tn-file-picker treats typed input as ONE path even in
18692
+ * multi-select mode (commas are legal in paths, so they are never list
18693
+ * separators): committing a typed path REPLACES the whole selection with
18694
+ * that single path, and commits go through the component's normal
18695
+ * validation — paths outside `rootPath` are rejected (the value stays
18696
+ * unchanged and an `error` is emitted), and `callbacks.validatePath` is
18697
+ * consulted when provided. Build a real multi-selection through the popup
18698
+ * with {@link clickItem} + {@link clickSelect}.
18699
+ *
18700
+ * With `allowFreeText`, the typed text is committed verbatim with no
18701
+ * validation, and in multi-select it is split on commas — so passing a
18702
+ * `string[]` (typed joined with `', '`) sets one entry per element.
18601
18703
  *
18602
- * Commits go through the component's normal validation: paths outside
18603
- * `rootPath` are rejected (the value stays unchanged and an `error` is
18604
- * emitted), and `callbacks.validatePath` is consulted when provided.
18605
18704
  * Setting an empty string clears the selection. Has no effect when
18606
18705
  * `allowManualInput` is false (the input is readonly).
18607
18706
  *
18608
- * @param value The path to set.
18707
+ * @param value The path to set, or several entries for a free-text
18708
+ * multi-select picker.
18609
18709
  *
18610
18710
  * @example
18611
18711
  * ```typescript
18612
18712
  * await picker.setValue('/mnt/tank/media');
18713
+ * await freeTextMultiPicker.setValue(['/mnt/tank/a', 'EXTERNAL:host\\share']);
18613
18714
  * ```
18614
18715
  */
18615
- setValue(value: string): Promise<void>;
18716
+ setValue(value: string | string[]): Promise<void>;
18616
18717
  /**
18617
18718
  * Gets the path input's placeholder text.
18618
18719
  *