@truenas/ui-components 0.2.1 → 0.2.3

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.2.1",
3
+ "version": "0.2.3",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -603,6 +603,21 @@ tn-dialog-shell {
603
603
  gap: 16px;
604
604
  }
605
605
 
606
+ /* Hide a content section / actions footer that has nothing to show, so it
607
+ doesn't render as an empty bordered, padded bar.
608
+ - `:empty` covers dialogs that project nothing into the slot (the ng-content
609
+ comment anchor is ignored by `:empty`, but real text/elements are not).
610
+ - The `--hidden` modifier (driven by the [hideContent]/[hideActions] inputs)
611
+ covers slots that always project a wrapper element whose contents are
612
+ conditional, so the slot is never truly `:empty`.
613
+ Declared after the layout rules above so it wins on equal specificity. */
614
+ .tn-dialog__content:empty,
615
+ .tn-dialog__content--hidden,
616
+ .tn-dialog__actions:empty,
617
+ .tn-dialog__actions--hidden {
618
+ display: none;
619
+ }
620
+
606
621
  /* Destructive variant */
607
622
  .tn-dialog--destructive .tn-dialog__header {
608
623
  border-bottom-color: var(--tn-lines, #e5e7eb);
@@ -1288,6 +1288,14 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1288
1288
  * (e.g. `1.5 GiB`). Ignored unless `inputType` is `Size`.
1289
1289
  */
1290
1290
  sizeRound: _angular_core.InputSignal<number>;
1291
+ /**
1292
+ * Whether a `Password` field renders the built-in visibility toggle — the eye
1293
+ * button that switches the field between masked and plain-text display.
1294
+ * Defaults to true; set false for secrets that must never be revealed.
1295
+ * Setting `suffixIcon` suppresses the toggle automatically (a custom suffix
1296
+ * control replaces it). Ignored unless `inputType` is `Password`.
1297
+ */
1298
+ showPasswordToggle: _angular_core.InputSignal<boolean>;
1291
1299
  prefixIcon: _angular_core.InputSignal<string | undefined>;
1292
1300
  prefixIconLibrary: _angular_core.InputSignal<IconLibraryType | undefined>;
1293
1301
  suffixIcon: _angular_core.InputSignal<string | undefined>;
@@ -1308,12 +1316,44 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1308
1316
  isSize: _angular_core.Signal<boolean>;
1309
1317
  /** True when the field only accepts whole numbers (i.e. `allowDecimals` is false). */
1310
1318
  integerOnly: _angular_core.Signal<boolean>;
1311
- /** The `type` attribute actually rendered. Number and size modes use a text input: number avoids the native type="number" footguns, size must accept unit letters. */
1319
+ /** True when the field is a password field. */
1320
+ isPassword: _angular_core.Signal<boolean>;
1321
+ /**
1322
+ * Whether the password is currently revealed. Not exposed as an input so a
1323
+ * reveal is always an explicit user gesture, and linked to the toggle's own
1324
+ * availability so a revealed value never outlives the control that revealed
1325
+ * it: whenever the toggle goes away (the field leaves password mode,
1326
+ * `showPasswordToggle` flips off, a `suffixIcon` replaces it) or the field
1327
+ * is disabled, the field snaps back to masked.
1328
+ */
1329
+ protected passwordVisible: _angular_core.WritableSignal<boolean>;
1330
+ /** The `type` attribute actually rendered. Number and size modes use a text input: number avoids the native type="number" footguns, size must accept unit letters. A revealed password renders as text — flipping the type attribute is the standard reveal mechanism and preserves value and caret. */
1312
1331
  resolvedType: _angular_core.Signal<InputType>;
1313
1332
  /** `inputmode` hint: numeric keypad for integers, decimal keypad otherwise. Null (omitted) outside number mode — size fields accept unit letters, so they keep the full keyboard. */
1314
1333
  numericInputMode: _angular_core.Signal<"numeric" | "decimal" | null>;
1315
1334
  /** Number and size modes are always single-line; they win over `multiline` if both are set. */
1316
1335
  showTextarea: _angular_core.Signal<boolean>;
1336
+ /**
1337
+ * The visibility toggle renders only on single-line password fields (a
1338
+ * password+multiline combo renders a textarea, which has no `type` to flip),
1339
+ * and yields to a consumer-provided `suffixIcon` — a custom suffix control
1340
+ * replaces the built-in toggle rather than stacking a second button.
1341
+ */
1342
+ protected hasPasswordToggle: _angular_core.Signal<boolean>;
1343
+ /**
1344
+ * Icon for the visibility toggle, mirroring the field's current state: a
1345
+ * slashed eye while masked, an open eye while revealed. The literal
1346
+ * `tnIconMarker` calls double as build-time markers that pull both icons
1347
+ * into the sprite.
1348
+ */
1349
+ protected passwordToggleIcon: _angular_core.Signal<string>;
1350
+ /**
1351
+ * Role-first test-id segments for the visibility toggle:
1352
+ * `button-toggle-password[-<testId>]`. The toggle is fixed field chrome, so
1353
+ * the role leads (matching the dialog-shell close/fullscreen convention) and
1354
+ * automation can target every password toggle with one prefix selector.
1355
+ */
1356
+ protected passwordToggleTestId: _angular_core.Signal<(string | number | null | undefined)[]>;
1317
1357
  id: string;
1318
1358
  protected value: string;
1319
1359
  private formDisabled;
@@ -1330,12 +1370,13 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1330
1370
  setDisabledState(isDisabled: boolean): void;
1331
1371
  protected onValueChange(event: Event): void;
1332
1372
  protected onBlur(): void;
1373
+ protected togglePasswordVisibility(): void;
1333
1374
  /** Strips any character that can't appear in the current numeric mode (single leading '-', single '.' for decimals). */
1334
1375
  private sanitizeNumeric;
1335
1376
  /** Parses a sanitized string to a number, mapping empty/partial input to null (never 0). */
1336
1377
  private parseNumeric;
1337
1378
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnInputComponent, never>;
1338
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnInputComponent, "tn-input", never, { "inputType": { "alias": "inputType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "multiline": { "alias": "multiline"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "allowDecimals": { "alias": "allowDecimals"; "required": false; "isSignal": true; }; "sizeStandard": { "alias": "sizeStandard"; "required": false; "isSignal": true; }; "sizeDefaultUnit": { "alias": "sizeDefaultUnit"; "required": false; "isSignal": true; }; "sizeRound": { "alias": "sizeRound"; "required": false; "isSignal": true; }; "prefixIcon": { "alias": "prefixIcon"; "required": false; "isSignal": true; }; "prefixIconLibrary": { "alias": "prefixIconLibrary"; "required": false; "isSignal": true; }; "suffixIcon": { "alias": "suffixIcon"; "required": false; "isSignal": true; }; "suffixIconLibrary": { "alias": "suffixIconLibrary"; "required": false; "isSignal": true; }; "suffixIconAriaLabel": { "alias": "suffixIconAriaLabel"; "required": false; "isSignal": true; }; "suffixActionTestId": { "alias": "suffixActionTestId"; "required": false; "isSignal": true; }; }, { "onSuffixAction": "onSuffixAction"; }, never, never, true, never>;
1379
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnInputComponent, "tn-input", never, { "inputType": { "alias": "inputType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "multiline": { "alias": "multiline"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "allowDecimals": { "alias": "allowDecimals"; "required": false; "isSignal": true; }; "sizeStandard": { "alias": "sizeStandard"; "required": false; "isSignal": true; }; "sizeDefaultUnit": { "alias": "sizeDefaultUnit"; "required": false; "isSignal": true; }; "sizeRound": { "alias": "sizeRound"; "required": false; "isSignal": true; }; "showPasswordToggle": { "alias": "showPasswordToggle"; "required": false; "isSignal": true; }; "prefixIcon": { "alias": "prefixIcon"; "required": false; "isSignal": true; }; "prefixIconLibrary": { "alias": "prefixIconLibrary"; "required": false; "isSignal": true; }; "suffixIcon": { "alias": "suffixIcon"; "required": false; "isSignal": true; }; "suffixIconLibrary": { "alias": "suffixIconLibrary"; "required": false; "isSignal": true; }; "suffixIconAriaLabel": { "alias": "suffixIconAriaLabel"; "required": false; "isSignal": true; }; "suffixActionTestId": { "alias": "suffixActionTestId"; "required": false; "isSignal": true; }; }, { "onSuffixAction": "onSuffixAction"; }, never, never, true, never>;
1339
1380
  }
1340
1381
 
1341
1382
  /**
@@ -1565,6 +1606,7 @@ declare class TnInputHarness extends ComponentHarness {
1565
1606
  private prefixIconEl;
1566
1607
  private suffixButton;
1567
1608
  private suffixIconEl;
1609
+ private visibilityToggle;
1568
1610
  /**
1569
1611
  * Gets a `HarnessPredicate` that can be used to search for an input
1570
1612
  * with specific attributes.
@@ -1699,6 +1741,27 @@ declare class TnInputHarness extends ComponentHarness {
1699
1741
  * @returns Promise that resolves when the click action is complete.
1700
1742
  */
1701
1743
  clickSuffixAction(): Promise<void>;
1744
+ /**
1745
+ * Checks whether the password visibility toggle is present.
1746
+ *
1747
+ * @returns Promise resolving to true if the toggle button exists.
1748
+ */
1749
+ hasPasswordToggle(): Promise<boolean>;
1750
+ /**
1751
+ * Whether the password is currently revealed (the field renders as plain text).
1752
+ *
1753
+ * Only meaningful on password-type inputs; resolves false while masked.
1754
+ *
1755
+ * @returns Promise resolving to true when the value is shown in plain text.
1756
+ */
1757
+ isPasswordRevealed(): Promise<boolean>;
1758
+ /**
1759
+ * Clicks the password visibility toggle, switching between masked and
1760
+ * plain-text display.
1761
+ *
1762
+ * @returns Promise that resolves when the click action is complete.
1763
+ */
1764
+ togglePasswordVisibility(): Promise<void>;
1702
1765
  /**
1703
1766
  * Focuses the input element.
1704
1767
  *
@@ -6443,6 +6506,22 @@ declare class TnDialog {
6443
6506
  declare class TnDialogShellComponent implements OnInit {
6444
6507
  title: _angular_core.InputSignal<string>;
6445
6508
  showFullscreenButton: _angular_core.InputSignal<boolean>;
6509
+ /**
6510
+ * Show the header close (X) button. Disable for dialogs that must not be
6511
+ * dismissed from the chrome — e.g. a running job that can only be minimized.
6512
+ */
6513
+ showCloseButton: _angular_core.InputSignal<boolean>;
6514
+ /**
6515
+ * Hide the content section. Use when the body is projected through an
6516
+ * always-present wrapper whose contents are conditional, so the section is
6517
+ * never truly `:empty` (consumers cannot project from inside an `@if`, see
6518
+ * the dialog docs). An empty section with no wrapper is hidden automatically
6519
+ * via the `:empty` rule in the theme, so this input is only needed for the
6520
+ * wrapper case.
6521
+ */
6522
+ hideContent: _angular_core.InputSignal<boolean>;
6523
+ /** Hide the actions footer. Same wrapper-case rationale as {@link hideContent}. */
6524
+ hideActions: _angular_core.InputSignal<boolean>;
6446
6525
  /**
6447
6526
  * Optional semantic base that scopes the shell's chrome buttons. The close
6448
6527
  * and fullscreen buttons emit `button-close` / `button-fullscreen` by default,
@@ -6484,7 +6563,7 @@ declare class TnDialogShellComponent implements OnInit {
6484
6563
  private enterFullscreen;
6485
6564
  private exitFullscreen;
6486
6565
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnDialogShellComponent, never>;
6487
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnDialogShellComponent, "tn-dialog-shell", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "showFullscreenButton": { "alias": "showFullscreenButton"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; }, {}, never, ["*", "[tnDialogAction]"], true, never>;
6566
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnDialogShellComponent, "tn-dialog-shell", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "showFullscreenButton": { "alias": "showFullscreenButton"; "required": false; "isSignal": true; }; "showCloseButton": { "alias": "showCloseButton"; "required": false; "isSignal": true; }; "hideContent": { "alias": "hideContent"; "required": false; "isSignal": true; }; "hideActions": { "alias": "hideActions"; "required": false; "isSignal": true; }; "testId": { "alias": "testId"; "required": false; "isSignal": true; }; }, {}, never, ["*", "[tnDialogAction]"], true, never>;
6488
6567
  }
6489
6568
 
6490
6569
  /**