@truenas/ui-components 0.1.44 → 0.1.46

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.
@@ -4645,6 +4645,7 @@ class TnFormFieldComponent {
4645
4645
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
4646
4646
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
4647
4647
  testId = input('', ...(ngDevMode ? [{ debugName: "testId" }] : []));
4648
+ subscriptSizing = input('dynamic', ...(ngDevMode ? [{ debugName: "subscriptSizing" }] : []));
4648
4649
  control = contentChild(NgControl, ...(ngDevMode ? [{ debugName: "control" }] : []));
4649
4650
  hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
4650
4651
  errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
@@ -4708,13 +4709,16 @@ class TnFormFieldComponent {
4708
4709
  showHint = computed(() => {
4709
4710
  return !!this.hint() && !this.showError();
4710
4711
  }, ...(ngDevMode ? [{ debugName: "showHint" }] : []));
4712
+ showSubscript = computed(() => {
4713
+ return this.subscriptSizing() === 'fixed' || this.showError() || this.showHint();
4714
+ }, ...(ngDevMode ? [{ debugName: "showSubscript" }] : []));
4711
4715
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4712
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnFormFieldComponent, isStandalone: true, selector: "tn-form-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "control", first: true, predicate: NgControl, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-form-field\" [attr.data-testid]=\"testId()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"tn-form-field-label\" [class.required]=\"required()\">\n {{ label() }}\n @if (required()) {\n <span class=\"required-asterisk\" aria-label=\"required\">*</span>\n }\n </label>\n }\n\n <!-- Form Control Content -->\n <div class=\"tn-form-field-wrapper\">\n <ng-content />\n </div>\n\n <!-- Hint or Error Message -->\n <div class=\"tn-form-field-subscript\">\n @if (showError()) {\n <div\n class=\"tn-form-field-error\"\n role=\"alert\"\n aria-live=\"polite\">\n {{ errorMessage() }}\n </div>\n }\n @if (showHint()) {\n <div class=\"tn-form-field-hint\">\n {{ hint() }}\n </div>\n }\n </div>\n</div>", styles: [".tn-form-field{display:block;width:100%;margin-bottom:1rem;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-form-field-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--tn-fg1, #333);line-height:1.4}.tn-form-field-label.required .required-asterisk{color:var(--tn-error, #dc3545);margin-left:.25rem}.tn-form-field-wrapper{position:relative;width:100%;overflow:visible}.tn-form-field-wrapper :ng-deep .tn-select-container,.tn-form-field-wrapper :ng-deep .tn-input-container{margin-bottom:0}.tn-form-field-wrapper :ng-deep .tn-select-label,.tn-form-field-wrapper :ng-deep .tn-input-label{display:none}.tn-form-field-wrapper :ng-deep .tn-select-error,.tn-form-field-wrapper :ng-deep .tn-input-error{display:none}.tn-form-field-wrapper :ng-deep .tn-select-dropdown{z-index:1000}.tn-form-field-subscript{min-height:1.25rem;margin-top:.25rem;font-size:.75rem;line-height:1.4}.tn-form-field-error{color:var(--tn-error, #dc3545);margin:0}.tn-form-field-hint{color:var(--tn-fg2, #6c757d);margin:0}.tn-form-field-wrapper:has(:focus-visible) .tn-form-field-label{color:var(--tn-primary, #007bff)}.tn-form-field-wrapper:has(.error) .tn-form-field-label{color:var(--tn-error, #dc3545)}@media(prefers-reduced-motion:reduce){.tn-form-field-label{transition:none}}@media(prefers-contrast:high){.tn-form-field-label,.tn-form-field-error{font-weight:600}}\n"] });
4716
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnFormFieldComponent, isStandalone: true, selector: "tn-form-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "control", first: true, predicate: NgControl, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-form-field\" [attr.data-testid]=\"testId()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"tn-form-field-label\" [class.required]=\"required()\">\n {{ label() }}\n @if (required()) {\n <span class=\"required-asterisk\" aria-label=\"required\">*</span>\n }\n </label>\n }\n\n <!-- Form Control Content -->\n <div class=\"tn-form-field-wrapper\">\n <ng-content />\n </div>\n\n <!-- Hint or Error Message -->\n @if (showSubscript()) {\n <div class=\"tn-form-field-subscript\" [class.tn-form-field-subscript-dynamic]=\"subscriptSizing() === 'dynamic'\">\n @if (showError()) {\n <div\n class=\"tn-form-field-error\"\n role=\"alert\"\n aria-live=\"polite\">\n {{ errorMessage() }}\n </div>\n }\n @if (showHint()) {\n <div class=\"tn-form-field-hint\">\n {{ hint() }}\n </div>\n }\n </div>\n }\n</div>", styles: [".tn-form-field{display:block;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-form-field-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--tn-fg1, #333);line-height:1.4}.tn-form-field-label.required .required-asterisk{color:var(--tn-error, #dc3545);margin-left:.25rem}.tn-form-field-wrapper{position:relative;width:100%;overflow:visible}.tn-form-field-wrapper :ng-deep .tn-select-container,.tn-form-field-wrapper :ng-deep .tn-input-container{margin-bottom:0}.tn-form-field-wrapper :ng-deep .tn-select-label,.tn-form-field-wrapper :ng-deep .tn-input-label{display:none}.tn-form-field-wrapper :ng-deep .tn-select-error,.tn-form-field-wrapper :ng-deep .tn-input-error{display:none}.tn-form-field-wrapper :ng-deep .tn-select-dropdown{z-index:1000}.tn-form-field-subscript{min-height:1.25rem;margin-top:.25rem;font-size:.75rem;line-height:1.4}.tn-form-field-subscript-dynamic{min-height:0}.tn-form-field-error{color:var(--tn-error, #dc3545);margin:0}.tn-form-field-hint{color:var(--tn-fg2, #6c757d);margin:0}.tn-form-field-wrapper:has(:focus-visible) .tn-form-field-label{color:var(--tn-primary, #007bff)}.tn-form-field-wrapper:has(.error) .tn-form-field-label{color:var(--tn-error, #dc3545)}@media(prefers-reduced-motion:reduce){.tn-form-field-label{transition:none}}@media(prefers-contrast:high){.tn-form-field-label,.tn-form-field-error{font-weight:600}}\n"] });
4713
4717
  }
4714
4718
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnFormFieldComponent, decorators: [{
4715
4719
  type: Component,
4716
- args: [{ selector: 'tn-form-field', standalone: true, imports: [], template: "<div class=\"tn-form-field\" [attr.data-testid]=\"testId()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"tn-form-field-label\" [class.required]=\"required()\">\n {{ label() }}\n @if (required()) {\n <span class=\"required-asterisk\" aria-label=\"required\">*</span>\n }\n </label>\n }\n\n <!-- Form Control Content -->\n <div class=\"tn-form-field-wrapper\">\n <ng-content />\n </div>\n\n <!-- Hint or Error Message -->\n <div class=\"tn-form-field-subscript\">\n @if (showError()) {\n <div\n class=\"tn-form-field-error\"\n role=\"alert\"\n aria-live=\"polite\">\n {{ errorMessage() }}\n </div>\n }\n @if (showHint()) {\n <div class=\"tn-form-field-hint\">\n {{ hint() }}\n </div>\n }\n </div>\n</div>", styles: [".tn-form-field{display:block;width:100%;margin-bottom:1rem;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-form-field-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--tn-fg1, #333);line-height:1.4}.tn-form-field-label.required .required-asterisk{color:var(--tn-error, #dc3545);margin-left:.25rem}.tn-form-field-wrapper{position:relative;width:100%;overflow:visible}.tn-form-field-wrapper :ng-deep .tn-select-container,.tn-form-field-wrapper :ng-deep .tn-input-container{margin-bottom:0}.tn-form-field-wrapper :ng-deep .tn-select-label,.tn-form-field-wrapper :ng-deep .tn-input-label{display:none}.tn-form-field-wrapper :ng-deep .tn-select-error,.tn-form-field-wrapper :ng-deep .tn-input-error{display:none}.tn-form-field-wrapper :ng-deep .tn-select-dropdown{z-index:1000}.tn-form-field-subscript{min-height:1.25rem;margin-top:.25rem;font-size:.75rem;line-height:1.4}.tn-form-field-error{color:var(--tn-error, #dc3545);margin:0}.tn-form-field-hint{color:var(--tn-fg2, #6c757d);margin:0}.tn-form-field-wrapper:has(:focus-visible) .tn-form-field-label{color:var(--tn-primary, #007bff)}.tn-form-field-wrapper:has(.error) .tn-form-field-label{color:var(--tn-error, #dc3545)}@media(prefers-reduced-motion:reduce){.tn-form-field-label{transition:none}}@media(prefers-contrast:high){.tn-form-field-label,.tn-form-field-error{font-weight:600}}\n"] }]
4717
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], control: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { isSignal: true }] }] } });
4720
+ args: [{ selector: 'tn-form-field', standalone: true, imports: [], template: "<div class=\"tn-form-field\" [attr.data-testid]=\"testId()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"tn-form-field-label\" [class.required]=\"required()\">\n {{ label() }}\n @if (required()) {\n <span class=\"required-asterisk\" aria-label=\"required\">*</span>\n }\n </label>\n }\n\n <!-- Form Control Content -->\n <div class=\"tn-form-field-wrapper\">\n <ng-content />\n </div>\n\n <!-- Hint or Error Message -->\n @if (showSubscript()) {\n <div class=\"tn-form-field-subscript\" [class.tn-form-field-subscript-dynamic]=\"subscriptSizing() === 'dynamic'\">\n @if (showError()) {\n <div\n class=\"tn-form-field-error\"\n role=\"alert\"\n aria-live=\"polite\">\n {{ errorMessage() }}\n </div>\n }\n @if (showHint()) {\n <div class=\"tn-form-field-hint\">\n {{ hint() }}\n </div>\n }\n </div>\n }\n</div>", styles: [".tn-form-field{display:block;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-form-field-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--tn-fg1, #333);line-height:1.4}.tn-form-field-label.required .required-asterisk{color:var(--tn-error, #dc3545);margin-left:.25rem}.tn-form-field-wrapper{position:relative;width:100%;overflow:visible}.tn-form-field-wrapper :ng-deep .tn-select-container,.tn-form-field-wrapper :ng-deep .tn-input-container{margin-bottom:0}.tn-form-field-wrapper :ng-deep .tn-select-label,.tn-form-field-wrapper :ng-deep .tn-input-label{display:none}.tn-form-field-wrapper :ng-deep .tn-select-error,.tn-form-field-wrapper :ng-deep .tn-input-error{display:none}.tn-form-field-wrapper :ng-deep .tn-select-dropdown{z-index:1000}.tn-form-field-subscript{min-height:1.25rem;margin-top:.25rem;font-size:.75rem;line-height:1.4}.tn-form-field-subscript-dynamic{min-height:0}.tn-form-field-error{color:var(--tn-error, #dc3545);margin:0}.tn-form-field-hint{color:var(--tn-fg2, #6c757d);margin:0}.tn-form-field-wrapper:has(:focus-visible) .tn-form-field-label{color:var(--tn-primary, #007bff)}.tn-form-field-wrapper:has(.error) .tn-form-field-label{color:var(--tn-error, #dc3545)}@media(prefers-reduced-motion:reduce){.tn-form-field-label{transition:none}}@media(prefers-contrast:high){.tn-form-field-label,.tn-form-field-error{font-weight:600}}\n"] }]
4721
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], subscriptSizing: [{ type: i0.Input, args: [{ isSignal: true, alias: "subscriptSizing", required: false }] }], control: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { isSignal: true }] }] } });
4718
4722
 
4719
4723
  /**
4720
4724
  * Harness for interacting with `tn-form-field` in tests.
@@ -4871,6 +4875,40 @@ class TnFormFieldHarness extends ComponentHarness {
4871
4875
  const root = await this.locatorFor('.tn-form-field')();
4872
4876
  return root.getAttribute('data-testid');
4873
4877
  }
4878
+ /**
4879
+ * Checks whether the subscript wrapper is currently rendered.
4880
+ *
4881
+ * @returns Promise resolving to true if the subscript area is present in the DOM.
4882
+ *
4883
+ * @example
4884
+ * ```typescript
4885
+ * const field = await loader.getHarness(TnFormFieldHarness.with({ label: 'Name' }));
4886
+ * expect(await field.hasSubscript()).toBe(false);
4887
+ * ```
4888
+ */
4889
+ async hasSubscript() {
4890
+ const subscript = await this.locatorForOptional('.tn-form-field-subscript')();
4891
+ return subscript !== null;
4892
+ }
4893
+ /**
4894
+ * Gets the current subscript sizing mode.
4895
+ *
4896
+ * @returns Promise resolving to `'fixed'` or `'dynamic'`.
4897
+ *
4898
+ * @example
4899
+ * ```typescript
4900
+ * const field = await loader.getHarness(TnFormFieldHarness.with({ label: 'Name' }));
4901
+ * expect(await field.getSubscriptSizing()).toBe('dynamic');
4902
+ * ```
4903
+ */
4904
+ async getSubscriptSizing() {
4905
+ const subscript = await this.locatorForOptional('.tn-form-field-subscript')();
4906
+ if (!subscript) {
4907
+ return 'dynamic';
4908
+ }
4909
+ const isDynamic = await subscript.hasClass('tn-form-field-subscript-dynamic');
4910
+ return isDynamic ? 'dynamic' : 'fixed';
4911
+ }
4874
4912
  }
4875
4913
 
4876
4914
  class TnSelectComponent {