@truenas/ui-components 0.1.64 → 0.1.65

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.1.64",
3
+ "version": "0.1.65",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -952,11 +952,12 @@ interface IconButtonHarnessFilters extends BaseHarnessFilters {
952
952
 
953
953
  declare enum InputType {
954
954
  Email = "email",
955
+ Number = "number",
955
956
  Password = "password",
956
957
  PlainText = "text"
957
958
  }
958
959
 
959
- declare class TnInputComponent implements AfterViewInit, ControlValueAccessor {
960
+ declare class TnInputComponent implements AfterViewInit, OnDestroy, ControlValueAccessor {
960
961
  inputEl: _angular_core.Signal<ElementRef<HTMLInputElement | HTMLTextAreaElement>>;
961
962
  inputType: _angular_core.InputSignal<InputType>;
962
963
  placeholder: _angular_core.InputSignal<string>;
@@ -964,6 +965,25 @@ declare class TnInputComponent implements AfterViewInit, ControlValueAccessor {
964
965
  disabled: _angular_core.InputSignal<boolean>;
965
966
  multiline: _angular_core.InputSignal<boolean>;
966
967
  rows: _angular_core.InputSignal<number>;
968
+ /**
969
+ * Accessible name for the control. Rendered as `aria-label` on the input/textarea.
970
+ *
971
+ * Leave unset when the input is wrapped in a `tn-form-field` (or otherwise has a
972
+ * visible `<label>`); set it for standalone usage so the control isn't unnamed in
973
+ * the a11y tree.
974
+ */
975
+ ariaLabel: _angular_core.InputSignal<string | undefined>;
976
+ /**
977
+ * Integer/decimal switch — only meaningful when `inputType` is `InputType.Number`.
978
+ *
979
+ * - **`true` (default) → decimal mode**: accepts a single `.` and emits via
980
+ * `parseFloat`, so a `Number` field accepts `"3.5"` out of the box.
981
+ * - **`false` → integer mode**: strips `.` and emits via `parseInt`.
982
+ *
983
+ * Range enforcement is intentionally left to the consumer's form validators
984
+ * (e.g. `Validators.min`/`max`), which work because the control emits real numbers.
985
+ */
986
+ allowDecimals: _angular_core.InputSignal<boolean>;
967
987
  prefixIcon: _angular_core.InputSignal<string | undefined>;
968
988
  prefixIconLibrary: _angular_core.InputSignal<IconLibraryType | undefined>;
969
989
  suffixIcon: _angular_core.InputSignal<string | undefined>;
@@ -972,22 +992,37 @@ declare class TnInputComponent implements AfterViewInit, ControlValueAccessor {
972
992
  onSuffixAction: _angular_core.OutputEmitterRef<MouseEvent>;
973
993
  hasPrefixIcon: _angular_core.Signal<boolean>;
974
994
  hasSuffixIcon: _angular_core.Signal<boolean>;
995
+ isNumeric: _angular_core.Signal<boolean>;
996
+ /** True when the field only accepts whole numbers (i.e. `allowDecimals` is false). */
997
+ integerOnly: _angular_core.Signal<boolean>;
998
+ /** The `type` attribute actually rendered. Number mode uses a text input + inputmode to avoid the native type="number" footguns. */
999
+ resolvedType: _angular_core.Signal<InputType>;
1000
+ /** `inputmode` hint: numeric keypad for integers, decimal keypad otherwise. Null (omitted) when not in number mode. */
1001
+ numericInputMode: _angular_core.Signal<"numeric" | "decimal" | null>;
1002
+ /** Number mode is always single-line; it wins over `multiline` if both are set. */
1003
+ showTextarea: _angular_core.Signal<boolean>;
975
1004
  id: string;
976
- value: string;
1005
+ protected value: string;
977
1006
  private formDisabled;
978
1007
  isDisabled: _angular_core.Signal<boolean>;
979
1008
  private onChange;
980
1009
  private onTouched;
981
1010
  private focusMonitor;
1011
+ private monitoredEl?;
982
1012
  ngAfterViewInit(): void;
983
- writeValue(value: string): void;
984
- registerOnChange(fn: (value: string) => void): void;
1013
+ ngOnDestroy(): void;
1014
+ writeValue(value: string | number | null | undefined): void;
1015
+ registerOnChange(fn: (value: string | number | null) => void): void;
985
1016
  registerOnTouched(fn: () => void): void;
986
1017
  setDisabledState(isDisabled: boolean): void;
987
- onValueChange(event: Event): void;
988
- onBlur(): void;
1018
+ protected onValueChange(event: Event): void;
1019
+ protected onBlur(): void;
1020
+ /** Strips any character that can't appear in the current numeric mode (single leading '-', single '.' for decimals). */
1021
+ private sanitizeNumeric;
1022
+ /** Parses a sanitized string to a number, mapping empty/partial input to null (never 0). */
1023
+ private parseNumeric;
989
1024
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnInputComponent, never>;
990
- 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; }; "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>;
1025
+ 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; }; "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>;
991
1026
  }
992
1027
 
993
1028
  /**
@@ -1222,6 +1257,34 @@ declare class TnInputHarness extends ComponentHarness {
1222
1257
  * @param value The value to set.
1223
1258
  */
1224
1259
  setValue(value: string): Promise<void>;
1260
+ /**
1261
+ * Gets the current value parsed as a number, mirroring what the control emits in number mode.
1262
+ * Empty or non-numeric input resolves to null (never 0).
1263
+ *
1264
+ * @returns Promise resolving to the numeric value, or null.
1265
+ */
1266
+ getNumericValue(): Promise<number | null>;
1267
+ /**
1268
+ * Gets the `inputmode` attribute (e.g. 'numeric' or 'decimal' in number mode).
1269
+ *
1270
+ * @returns Promise resolving to the inputmode string, or null if unset.
1271
+ */
1272
+ getInputMode(): Promise<string | null>;
1273
+ /**
1274
+ * Whether the field is in integer-only mode (i.e. `allowDecimals` is false).
1275
+ *
1276
+ * Derived from `inputmode`: number mode renders `numeric` for integers and
1277
+ * `decimal` otherwise. A convenience wrapper so tests need not know that mapping.
1278
+ *
1279
+ * @returns Promise resolving to true when only whole numbers are accepted.
1280
+ */
1281
+ isIntegerOnly(): Promise<boolean>;
1282
+ /**
1283
+ * Gets the `aria-label` (accessible name set via the `ariaLabel` input).
1284
+ *
1285
+ * @returns Promise resolving to the aria-label string, or null if unset.
1286
+ */
1287
+ getAriaLabel(): Promise<string | null>;
1225
1288
  /**
1226
1289
  * Gets the placeholder text.
1227
1290
  *