@truenas/ui-components 0.2.0 → 0.2.2

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.0",
3
+ "version": "0.2.2",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -1229,6 +1229,36 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1229
1229
  * the a11y tree.
1230
1230
  */
1231
1231
  ariaLabel: _angular_core.InputSignal<string | undefined>;
1232
+ /**
1233
+ * Native `autocomplete` hint rendered on the input/textarea. Pass the standard
1234
+ * autofill tokens (`'username'`, `'current-password'`, `'new-password'`,
1235
+ * `'one-time-code'`, ...) so browsers and password managers can identify and
1236
+ * fill the field.
1237
+ */
1238
+ autocomplete: _angular_core.InputSignal<string | undefined>;
1239
+ /**
1240
+ * Native `name` attribute rendered on the input/textarea. Browsers and password
1241
+ * managers use it to identify the field; typically mirrors the form control name.
1242
+ */
1243
+ name: _angular_core.InputSignal<string | undefined>;
1244
+ /**
1245
+ * Renders the native `readonly` attribute: the value is visible, focusable and
1246
+ * selectable but not editable. Unlike `disabled`, a readonly field stays in the
1247
+ * tab order and its form control stays enabled.
1248
+ */
1249
+ readonly: _angular_core.InputSignal<boolean>;
1250
+ /**
1251
+ * Renders the native `required` attribute so browsers and assistive technology
1252
+ * expose the field as required. Validation itself stays with the consumer's form
1253
+ * validators (e.g. `Validators.required`); forms that fully own validation UX
1254
+ * should also set `novalidate` to suppress native submit blocking.
1255
+ *
1256
+ * Note: this drives only the native/a11y semantics. When wrapped in a
1257
+ * `tn-form-field`, the visual `*` indicator is inferred automatically from the
1258
+ * control's `Validators.required`; only validator-less setups need the form
1259
+ * field's own `required` input alongside this one.
1260
+ */
1261
+ required: _angular_core.InputSignal<boolean>;
1232
1262
  /**
1233
1263
  * Integer/decimal switch — only meaningful when `inputType` is `InputType.Number`.
1234
1264
  *
@@ -1258,11 +1288,26 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1258
1288
  * (e.g. `1.5 GiB`). Ignored unless `inputType` is `Size`.
1259
1289
  */
1260
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>;
1261
1299
  prefixIcon: _angular_core.InputSignal<string | undefined>;
1262
1300
  prefixIconLibrary: _angular_core.InputSignal<IconLibraryType | undefined>;
1263
1301
  suffixIcon: _angular_core.InputSignal<string | undefined>;
1264
1302
  suffixIconLibrary: _angular_core.InputSignal<IconLibraryType | undefined>;
1265
1303
  suffixIconAriaLabel: _angular_core.InputSignal<string | undefined>;
1304
+ /**
1305
+ * Semantic test-id base for the suffix-action button. The library prepends the
1306
+ * element type (`button`) and renders the result under whichever attribute name
1307
+ * is configured via `TN_TEST_ATTR` (default `data-testid`) — e.g.
1308
+ * `suffixActionTestId="toggle-password"` → `button-toggle-password`.
1309
+ */
1310
+ suffixActionTestId: _angular_core.InputSignal<TnTestIdValue>;
1266
1311
  onSuffixAction: _angular_core.OutputEmitterRef<MouseEvent>;
1267
1312
  hasPrefixIcon: _angular_core.Signal<boolean>;
1268
1313
  hasSuffixIcon: _angular_core.Signal<boolean>;
@@ -1271,12 +1316,44 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1271
1316
  isSize: _angular_core.Signal<boolean>;
1272
1317
  /** True when the field only accepts whole numbers (i.e. `allowDecimals` is false). */
1273
1318
  integerOnly: _angular_core.Signal<boolean>;
1274
- /** 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. */
1275
1331
  resolvedType: _angular_core.Signal<InputType>;
1276
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. */
1277
1333
  numericInputMode: _angular_core.Signal<"numeric" | "decimal" | null>;
1278
1334
  /** Number and size modes are always single-line; they win over `multiline` if both are set. */
1279
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)[]>;
1280
1357
  id: string;
1281
1358
  protected value: string;
1282
1359
  private formDisabled;
@@ -1293,12 +1370,13 @@ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValue
1293
1370
  setDisabledState(isDisabled: boolean): void;
1294
1371
  protected onValueChange(event: Event): void;
1295
1372
  protected onBlur(): void;
1373
+ protected togglePasswordVisibility(): void;
1296
1374
  /** Strips any character that can't appear in the current numeric mode (single leading '-', single '.' for decimals). */
1297
1375
  private sanitizeNumeric;
1298
1376
  /** Parses a sanitized string to a number, mapping empty/partial input to null (never 0). */
1299
1377
  private parseNumeric;
1300
1378
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnInputComponent, never>;
1301
- 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; }; "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; }; }, { "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>;
1302
1380
  }
1303
1381
 
1304
1382
  /**
@@ -1528,6 +1606,7 @@ declare class TnInputHarness extends ComponentHarness {
1528
1606
  private prefixIconEl;
1529
1607
  private suffixButton;
1530
1608
  private suffixIconEl;
1609
+ private visibilityToggle;
1531
1610
  /**
1532
1611
  * Gets a `HarnessPredicate` that can be used to search for an input
1533
1612
  * with specific attributes.
@@ -1590,6 +1669,30 @@ declare class TnInputHarness extends ComponentHarness {
1590
1669
  * @returns Promise resolving to the aria-label string, or null if unset.
1591
1670
  */
1592
1671
  getAriaLabel(): Promise<string | null>;
1672
+ /**
1673
+ * Gets the native `name` attribute (set via the `name` input).
1674
+ *
1675
+ * @returns Promise resolving to the name string, or null if unset.
1676
+ */
1677
+ getName(): Promise<string | null>;
1678
+ /**
1679
+ * Gets the native `autocomplete` attribute (set via the `autocomplete` input).
1680
+ *
1681
+ * @returns Promise resolving to the autocomplete token, or null if unset.
1682
+ */
1683
+ getAutocomplete(): Promise<string | null>;
1684
+ /**
1685
+ * Checks whether the input is readonly (set via the `readonly` input).
1686
+ *
1687
+ * @returns Promise resolving to true if the input is readonly.
1688
+ */
1689
+ isReadonly(): Promise<boolean>;
1690
+ /**
1691
+ * Checks whether the input is marked required (set via the `required` input).
1692
+ *
1693
+ * @returns Promise resolving to true if the input is required.
1694
+ */
1695
+ isRequired(): Promise<boolean>;
1593
1696
  /**
1594
1697
  * Gets the placeholder text.
1595
1698
  *
@@ -1638,6 +1741,27 @@ declare class TnInputHarness extends ComponentHarness {
1638
1741
  * @returns Promise that resolves when the click action is complete.
1639
1742
  */
1640
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>;
1641
1765
  /**
1642
1766
  * Focuses the input element.
1643
1767
  *
@@ -1657,6 +1781,8 @@ declare class TnInputHarness extends ComponentHarness {
1657
1781
  interface InputHarnessFilters extends BaseHarnessFilters {
1658
1782
  /** Filters by placeholder text. */
1659
1783
  placeholder?: string;
1784
+ /** Filters by the native `name` attribute (typically the form control name). */
1785
+ name?: string;
1660
1786
  }
1661
1787
 
1662
1788
  declare class TnInputDirective {
@@ -3254,6 +3380,17 @@ type SubscriptSizing = 'fixed' | 'dynamic';
3254
3380
  declare class TnFormFieldComponent implements AfterContentInit {
3255
3381
  label: _angular_core.InputSignal<string>;
3256
3382
  hint: _angular_core.InputSignal<string>;
3383
+ /**
3384
+ * Forces the visual `*` required indicator next to the label. Usually
3385
+ * unnecessary: the indicator is inferred automatically when the projected
3386
+ * control carries `Validators.required`. Set this only when inference can't
3387
+ * see the requirement — e.g. a validator wrapped in `Validators.compose(...)`
3388
+ * or a custom validator that emits a `required`-style error.
3389
+ *
3390
+ * The indicator is purely visual — for native/a11y semantics pair it with the
3391
+ * projected control's own `required` input (e.g. `tn-input`'s, which renders
3392
+ * the native attribute).
3393
+ */
3257
3394
  required: _angular_core.InputSignal<boolean>;
3258
3395
  testId: _angular_core.InputSignal<TnTestIdValue>;
3259
3396
  subscriptSizing: _angular_core.InputSignal<SubscriptSizing>;
@@ -3282,6 +3419,13 @@ declare class TnFormFieldComponent implements AfterContentInit {
3282
3419
  * read this so the derived state stays reactive.
3283
3420
  */
3284
3421
  private controlState;
3422
+ /**
3423
+ * Whether the required indicator renders: forced via the `required` input, or
3424
+ * inferred from the projected control's validators (mirrors Angular Material's
3425
+ * `hasValidator(Validators.required)` approach — reference equality, so composed
3426
+ * or custom required-like validators need the explicit input).
3427
+ */
3428
+ protected showRequired: _angular_core.Signal<boolean>;
3285
3429
  protected hasError: _angular_core.Signal<boolean>;
3286
3430
  protected errorMessage: _angular_core.Signal<string>;
3287
3431
  ngAfterContentInit(): void;