@truenas/ui-components 0.1.13 → 0.1.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.
@@ -1119,6 +1119,15 @@ class TnInputComponent {
1119
1119
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1120
1120
  multiline = input(false, ...(ngDevMode ? [{ debugName: "multiline" }] : []));
1121
1121
  rows = input(3, ...(ngDevMode ? [{ debugName: "rows" }] : []));
1122
+ // Icon inputs
1123
+ prefixIcon = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIcon" }] : []));
1124
+ prefixIconLibrary = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconLibrary" }] : []));
1125
+ suffixIcon = input(undefined, ...(ngDevMode ? [{ debugName: "suffixIcon" }] : []));
1126
+ suffixIconLibrary = input(undefined, ...(ngDevMode ? [{ debugName: "suffixIconLibrary" }] : []));
1127
+ suffixIconAriaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "suffixIconAriaLabel" }] : []));
1128
+ onSuffixAction = output();
1129
+ hasPrefixIcon = computed(() => !!this.prefixIcon(), ...(ngDevMode ? [{ debugName: "hasPrefixIcon" }] : []));
1130
+ hasSuffixIcon = computed(() => !!this.suffixIcon(), ...(ngDevMode ? [{ debugName: "hasSuffixIcon" }] : []));
1122
1131
  id = 'tn-input';
1123
1132
  value = '';
1124
1133
  // CVA disabled state management
@@ -1153,24 +1162,425 @@ class TnInputComponent {
1153
1162
  this.onTouched();
1154
1163
  }
1155
1164
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1156
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnInputComponent, isStandalone: true, selector: "tn-input", inputs: { inputType: { classPropertyName: "inputType", publicName: "inputType", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnInputComponent, isStandalone: true, selector: "tn-input", inputs: { inputType: { classPropertyName: "inputType", publicName: "inputType", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, prefixIcon: { classPropertyName: "prefixIcon", publicName: "prefixIcon", isSignal: true, isRequired: false, transformFunction: null }, prefixIconLibrary: { classPropertyName: "prefixIconLibrary", publicName: "prefixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIcon: { classPropertyName: "suffixIcon", publicName: "suffixIcon", isSignal: true, isRequired: false, transformFunction: null }, suffixIconLibrary: { classPropertyName: "suffixIconLibrary", publicName: "suffixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIconAriaLabel: { classPropertyName: "suffixIconAriaLabel", publicName: "suffixIconAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSuffixAction: "onSuffixAction" }, providers: [
1157
1166
  {
1158
1167
  provide: NG_VALUE_ACCESSOR,
1159
1168
  useExisting: forwardRef(() => TnInputComponent),
1160
1169
  multi: true
1161
1170
  }
1162
- ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-input-container\">\n <!-- Regular input field -->\n @if (!multiline()) {\n <input\n #inputEl\n class=\"tn-input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"inputType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (multiline()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n</div>\n", styles: [".tn-input-container{position:relative;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-input{display:block;width:100%;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:focus{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input:disabled{background-color:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-fg2, #6c757d);cursor:not-allowed;opacity:.6}.tn-input.error{border-color:var(--tn-error, #dc3545)}.tn-input.error:focus{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input{transition:none}}@media(prefers-contrast:high){.tn-input{border-width:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }] });
1171
+ ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!multiline()) {\n <input\n #inputEl\n class=\"tn-input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"inputType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (multiline()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: TnIconComponent, selector: "tn-icon", inputs: ["name", "size", "color", "tooltip", "ariaLabel", "library", "fullSize", "customSize"] }] });
1163
1172
  }
1164
1173
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnInputComponent, decorators: [{
1165
1174
  type: Component,
1166
- args: [{ selector: 'tn-input', standalone: true, imports: [FormsModule, A11yModule], providers: [
1175
+ args: [{ selector: 'tn-input', standalone: true, imports: [FormsModule, A11yModule, TnIconComponent], providers: [
1167
1176
  {
1168
1177
  provide: NG_VALUE_ACCESSOR,
1169
1178
  useExisting: forwardRef(() => TnInputComponent),
1170
1179
  multi: true
1171
1180
  }
1172
- ], template: "<div class=\"tn-input-container\">\n <!-- Regular input field -->\n @if (!multiline()) {\n <input\n #inputEl\n class=\"tn-input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"inputType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (multiline()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n</div>\n", styles: [".tn-input-container{position:relative;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-input{display:block;width:100%;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:focus{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input:disabled{background-color:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-fg2, #6c757d);cursor:not-allowed;opacity:.6}.tn-input.error{border-color:var(--tn-error, #dc3545)}.tn-input.error:focus{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input{transition:none}}@media(prefers-contrast:high){.tn-input{border-width:2px}}\n"] }]
1173
- }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], inputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputType", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }] } });
1181
+ ], template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!multiline()) {\n <input\n #inputEl\n class=\"tn-input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"inputType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (multiline()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.placeholder]=\"placeholder()\"\n [attr.data-testid]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"] }]
1182
+ }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], inputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputType", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], prefixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIcon", required: false }] }], prefixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconLibrary", required: false }] }], suffixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIcon", required: false }] }], suffixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconLibrary", required: false }] }], suffixIconAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconAriaLabel", required: false }] }], onSuffixAction: [{ type: i0.Output, args: ["onSuffixAction"] }] } });
1183
+
1184
+ /**
1185
+ * Harness for interacting with tn-icon in tests.
1186
+ * Provides filtering by icon name and library for existence checks, as well as click interaction.
1187
+ *
1188
+ * @example
1189
+ * ```typescript
1190
+ * // Check for existence
1191
+ * const icon = await loader.getHarness(TnIconHarness);
1192
+ *
1193
+ * // Find icon by name
1194
+ * const folderIcon = await loader.getHarness(
1195
+ * TnIconHarness.with({ name: 'folder' })
1196
+ * );
1197
+ *
1198
+ * // Find icon by name and library
1199
+ * const mdiIcon = await loader.getHarness(
1200
+ * TnIconHarness.with({ name: 'account-circle', library: 'mdi' })
1201
+ * );
1202
+ *
1203
+ * // Check if icon exists
1204
+ * const hasIcon = await loader.hasHarness(
1205
+ * TnIconHarness.with({ name: 'check' })
1206
+ * );
1207
+ *
1208
+ * // Click an icon
1209
+ * const closeIcon = await loader.getHarness(
1210
+ * TnIconHarness.with({ name: 'close' })
1211
+ * );
1212
+ * await closeIcon.click();
1213
+ * ```
1214
+ */
1215
+ class TnIconHarness extends ComponentHarness {
1216
+ /**
1217
+ * The selector for the host element of a `TnIconComponent` instance.
1218
+ */
1219
+ static hostSelector = 'tn-icon';
1220
+ /**
1221
+ * Gets a `HarnessPredicate` that can be used to search for an icon
1222
+ * with specific attributes.
1223
+ *
1224
+ * @param options Options for filtering which icon instances are considered a match.
1225
+ * @returns A `HarnessPredicate` configured with the given options.
1226
+ *
1227
+ * @example
1228
+ * ```typescript
1229
+ * // Find icon by name
1230
+ * const icon = await loader.getHarness(
1231
+ * TnIconHarness.with({ name: 'home' })
1232
+ * );
1233
+ *
1234
+ * // Find icon by library
1235
+ * const customIcon = await loader.getHarness(
1236
+ * TnIconHarness.with({ library: 'custom' })
1237
+ * );
1238
+ *
1239
+ * // Find icon with specific size
1240
+ * const largeIcon = await loader.getHarness(
1241
+ * TnIconHarness.with({ size: 'lg' })
1242
+ * );
1243
+ * ```
1244
+ */
1245
+ static with(options = {}) {
1246
+ return new HarnessPredicate(TnIconHarness, options)
1247
+ .addOption('name', options.name, async (harness, name) => {
1248
+ return (await harness.getName()) === name;
1249
+ })
1250
+ .addOption('library', options.library, async (harness, library) => {
1251
+ return (await harness.getLibrary()) === library;
1252
+ })
1253
+ .addOption('size', options.size, async (harness, size) => {
1254
+ return (await harness.getSize()) === size;
1255
+ })
1256
+ .addOption('fullSize', options.fullSize, async (harness, fullSize) => {
1257
+ return (await harness.isFullSize()) === fullSize;
1258
+ })
1259
+ .addOption('customSize', options.customSize, async (harness, customSize) => {
1260
+ return (await harness.getCustomSize()) === customSize;
1261
+ });
1262
+ }
1263
+ /**
1264
+ * Gets the icon name.
1265
+ *
1266
+ * @returns Promise resolving to the icon name.
1267
+ *
1268
+ * @example
1269
+ * ```typescript
1270
+ * const icon = await loader.getHarness(TnIconHarness);
1271
+ * const name = await icon.getName();
1272
+ * expect(name).toBe('folder');
1273
+ * ```
1274
+ */
1275
+ async getName() {
1276
+ const host = await this.host();
1277
+ return host.getAttribute('name');
1278
+ }
1279
+ /**
1280
+ * Gets the icon library.
1281
+ *
1282
+ * @returns Promise resolving to the icon library.
1283
+ *
1284
+ * @example
1285
+ * ```typescript
1286
+ * const icon = await loader.getHarness(TnIconHarness);
1287
+ * const library = await icon.getLibrary();
1288
+ * expect(library).toBe('mdi');
1289
+ * ```
1290
+ */
1291
+ async getLibrary() {
1292
+ const host = await this.host();
1293
+ return host.getAttribute('library');
1294
+ }
1295
+ /**
1296
+ * Gets the icon size.
1297
+ *
1298
+ * @returns Promise resolving to the icon size.
1299
+ *
1300
+ * @example
1301
+ * ```typescript
1302
+ * const icon = await loader.getHarness(TnIconHarness);
1303
+ * const size = await icon.getSize();
1304
+ * expect(size).toBe('lg');
1305
+ * ```
1306
+ */
1307
+ async getSize() {
1308
+ const host = await this.host();
1309
+ return host.getAttribute('size');
1310
+ }
1311
+ /**
1312
+ * Gets the icon color.
1313
+ *
1314
+ * @returns Promise resolving to the icon color.
1315
+ *
1316
+ * @example
1317
+ * ```typescript
1318
+ * const icon = await loader.getHarness(TnIconHarness);
1319
+ * const color = await icon.getColor();
1320
+ * expect(color).toBe('primary');
1321
+ * ```
1322
+ */
1323
+ async getColor() {
1324
+ const host = await this.host();
1325
+ return host.getAttribute('color');
1326
+ }
1327
+ /**
1328
+ * Checks if the icon is in full-size mode.
1329
+ *
1330
+ * @returns Promise resolving to true if the icon is full-size, false otherwise.
1331
+ *
1332
+ * @example
1333
+ * ```typescript
1334
+ * const icon = await loader.getHarness(TnIconHarness);
1335
+ * const isFullSize = await icon.isFullSize();
1336
+ * expect(isFullSize).toBe(true);
1337
+ * ```
1338
+ */
1339
+ async isFullSize() {
1340
+ const host = await this.host();
1341
+ const fullSizeAttr = await host.getAttribute('full-size');
1342
+ return fullSizeAttr === 'true';
1343
+ }
1344
+ /**
1345
+ * Gets the icon custom size.
1346
+ *
1347
+ * @returns Promise resolving to the custom size value, or null if not set.
1348
+ *
1349
+ * @example
1350
+ * ```typescript
1351
+ * const icon = await loader.getHarness(TnIconHarness);
1352
+ * const customSize = await icon.getCustomSize();
1353
+ * expect(customSize).toBe('64px');
1354
+ * ```
1355
+ */
1356
+ async getCustomSize() {
1357
+ const host = await this.host();
1358
+ return host.getAttribute('custom-size');
1359
+ }
1360
+ /**
1361
+ * Checks if the icon is using a custom size.
1362
+ *
1363
+ * @returns Promise resolving to true if a custom size is set, false otherwise.
1364
+ *
1365
+ * @example
1366
+ * ```typescript
1367
+ * const icon = await loader.getHarness(TnIconHarness);
1368
+ * const hasCustomSize = await icon.hasCustomSize();
1369
+ * expect(hasCustomSize).toBe(true);
1370
+ * ```
1371
+ */
1372
+ async hasCustomSize() {
1373
+ const customSize = await this.getCustomSize();
1374
+ return customSize !== null;
1375
+ }
1376
+ /**
1377
+ * Clicks the icon.
1378
+ *
1379
+ * @returns Promise that resolves when the click action is complete.
1380
+ *
1381
+ * @example
1382
+ * ```typescript
1383
+ * const icon = await loader.getHarness(TnIconHarness.with({ name: 'close' }));
1384
+ * await icon.click();
1385
+ * ```
1386
+ */
1387
+ async click() {
1388
+ const host = await this.host();
1389
+ return host.click();
1390
+ }
1391
+ }
1392
+
1393
+ /**
1394
+ * Harness for interacting with tn-input in tests.
1395
+ * Provides methods for querying state, setting values, and interacting with prefix/suffix icons.
1396
+ *
1397
+ * @example
1398
+ * ```typescript
1399
+ * // Get the input harness
1400
+ * const input = await loader.getHarness(TnInputHarness);
1401
+ *
1402
+ * // Set and read a value
1403
+ * await input.setValue('hello');
1404
+ * expect(await input.getValue()).toBe('hello');
1405
+ *
1406
+ * // Check for prefix icon
1407
+ * expect(await input.hasPrefixIcon()).toBe(true);
1408
+ *
1409
+ * // Click suffix action
1410
+ * await input.clickSuffixAction();
1411
+ * ```
1412
+ */
1413
+ class TnInputHarness extends ComponentHarness {
1414
+ /**
1415
+ * The selector for the host element of a `TnInputComponent` instance.
1416
+ */
1417
+ static hostSelector = 'tn-input';
1418
+ inputEl = this.locatorFor('input.tn-input');
1419
+ textareaEl = this.locatorFor('textarea.tn-input');
1420
+ prefixIconEl = this.locatorForOptional('tn-icon.tn-input__prefix-icon');
1421
+ suffixButton = this.locatorForOptional('.tn-input__suffix-action');
1422
+ suffixIconEl = this.locatorForOptional(TnIconHarness.with({ ancestor: '.tn-input__suffix-action' }));
1423
+ /**
1424
+ * Gets a `HarnessPredicate` that can be used to search for an input
1425
+ * with specific attributes.
1426
+ *
1427
+ * @param options Options for filtering which input instances are considered a match.
1428
+ * @returns A `HarnessPredicate` configured with the given options.
1429
+ */
1430
+ static with(options = {}) {
1431
+ return new HarnessPredicate(TnInputHarness, options)
1432
+ .addOption('placeholder', options.placeholder, async (harness, placeholder) => {
1433
+ return (await harness.getPlaceholder()) === placeholder;
1434
+ });
1435
+ }
1436
+ /**
1437
+ * Gets the current value of the input.
1438
+ *
1439
+ * @returns Promise resolving to the input value.
1440
+ */
1441
+ async getValue() {
1442
+ if (await this.isMultiline()) {
1443
+ const textarea = await this.textareaEl();
1444
+ return (await textarea.getProperty('value')) ?? '';
1445
+ }
1446
+ const input = await this.inputEl();
1447
+ return (await input.getProperty('value')) ?? '';
1448
+ }
1449
+ /**
1450
+ * Sets the value of the input by clearing and typing.
1451
+ *
1452
+ * @param value The value to set.
1453
+ */
1454
+ async setValue(value) {
1455
+ if (await this.isMultiline()) {
1456
+ const textarea = await this.textareaEl();
1457
+ await textarea.clear();
1458
+ await textarea.sendKeys(value);
1459
+ return;
1460
+ }
1461
+ const input = await this.inputEl();
1462
+ await input.clear();
1463
+ await input.sendKeys(value);
1464
+ }
1465
+ /**
1466
+ * Gets the placeholder text.
1467
+ *
1468
+ * @returns Promise resolving to the placeholder string.
1469
+ */
1470
+ async getPlaceholder() {
1471
+ if (await this.isMultiline()) {
1472
+ const textarea = await this.textareaEl();
1473
+ return textarea.getAttribute('placeholder');
1474
+ }
1475
+ const input = await this.inputEl();
1476
+ return input.getAttribute('placeholder');
1477
+ }
1478
+ /**
1479
+ * Checks whether the input is disabled.
1480
+ *
1481
+ * @returns Promise resolving to true if the input is disabled.
1482
+ */
1483
+ async isDisabled() {
1484
+ if (await this.isMultiline()) {
1485
+ const textarea = await this.textareaEl();
1486
+ return (await textarea.getProperty('disabled')) ?? false;
1487
+ }
1488
+ const input = await this.inputEl();
1489
+ return (await input.getProperty('disabled')) ?? false;
1490
+ }
1491
+ /**
1492
+ * Checks whether the input renders as a textarea.
1493
+ *
1494
+ * @returns Promise resolving to true if multiline.
1495
+ */
1496
+ async isMultiline() {
1497
+ const textareas = await this.locatorForAll('textarea.tn-input')();
1498
+ return textareas.length > 0;
1499
+ }
1500
+ /**
1501
+ * Checks whether a prefix icon is present.
1502
+ *
1503
+ * @returns Promise resolving to true if a prefix icon exists.
1504
+ */
1505
+ async hasPrefixIcon() {
1506
+ const icon = await this.prefixIconEl();
1507
+ return icon !== null;
1508
+ }
1509
+ /**
1510
+ * Gets the prefix icon harness for further inspection.
1511
+ *
1512
+ * @returns Promise resolving to the prefix TnIconHarness, or null if not present.
1513
+ */
1514
+ async getPrefixIcon() {
1515
+ const el = await this.prefixIconEl();
1516
+ if (!el) {
1517
+ return null;
1518
+ }
1519
+ const allIcons = await this.locatorForAll(TnIconHarness)();
1520
+ for (const icon of allIcons) {
1521
+ const host = await icon.host();
1522
+ if (await host.hasClass('tn-input__prefix-icon')) {
1523
+ return icon;
1524
+ }
1525
+ }
1526
+ return null;
1527
+ }
1528
+ /**
1529
+ * Checks whether a suffix action button is present.
1530
+ *
1531
+ * @returns Promise resolving to true if a suffix action exists.
1532
+ */
1533
+ async hasSuffixAction() {
1534
+ const button = await this.suffixButton();
1535
+ return button !== null;
1536
+ }
1537
+ /**
1538
+ * Gets the suffix icon harness for further inspection.
1539
+ *
1540
+ * @returns Promise resolving to the suffix TnIconHarness, or null if not present.
1541
+ */
1542
+ async getSuffixIcon() {
1543
+ return this.suffixIconEl();
1544
+ }
1545
+ /**
1546
+ * Clicks the suffix action button.
1547
+ *
1548
+ * @returns Promise that resolves when the click action is complete.
1549
+ */
1550
+ async clickSuffixAction() {
1551
+ const button = await this.suffixButton();
1552
+ if (!button) {
1553
+ throw new Error('No suffix action button found on this input.');
1554
+ }
1555
+ return button.click();
1556
+ }
1557
+ /**
1558
+ * Focuses the input element.
1559
+ *
1560
+ * @returns Promise that resolves when the input is focused.
1561
+ */
1562
+ async focus() {
1563
+ if (await this.isMultiline()) {
1564
+ const textarea = await this.textareaEl();
1565
+ return textarea.focus();
1566
+ }
1567
+ const input = await this.inputEl();
1568
+ return input.focus();
1569
+ }
1570
+ /**
1571
+ * Blurs the input element.
1572
+ *
1573
+ * @returns Promise that resolves when the input is blurred.
1574
+ */
1575
+ async blur() {
1576
+ if (await this.isMultiline()) {
1577
+ const textarea = await this.textareaEl();
1578
+ return textarea.blur();
1579
+ }
1580
+ const input = await this.inputEl();
1581
+ return input.blur();
1582
+ }
1583
+ }
1174
1584
 
1175
1585
  class TnInputDirective {
1176
1586
  constructor() { }
@@ -2762,215 +3172,6 @@ class TnSelectHarness extends ComponentHarness {
2762
3172
  }
2763
3173
  }
2764
3174
 
2765
- /**
2766
- * Harness for interacting with tn-icon in tests.
2767
- * Provides filtering by icon name and library for existence checks, as well as click interaction.
2768
- *
2769
- * @example
2770
- * ```typescript
2771
- * // Check for existence
2772
- * const icon = await loader.getHarness(TnIconHarness);
2773
- *
2774
- * // Find icon by name
2775
- * const folderIcon = await loader.getHarness(
2776
- * TnIconHarness.with({ name: 'folder' })
2777
- * );
2778
- *
2779
- * // Find icon by name and library
2780
- * const mdiIcon = await loader.getHarness(
2781
- * TnIconHarness.with({ name: 'account-circle', library: 'mdi' })
2782
- * );
2783
- *
2784
- * // Check if icon exists
2785
- * const hasIcon = await loader.hasHarness(
2786
- * TnIconHarness.with({ name: 'check' })
2787
- * );
2788
- *
2789
- * // Click an icon
2790
- * const closeIcon = await loader.getHarness(
2791
- * TnIconHarness.with({ name: 'close' })
2792
- * );
2793
- * await closeIcon.click();
2794
- * ```
2795
- */
2796
- class TnIconHarness extends ComponentHarness {
2797
- /**
2798
- * The selector for the host element of a `TnIconComponent` instance.
2799
- */
2800
- static hostSelector = 'tn-icon';
2801
- /**
2802
- * Gets a `HarnessPredicate` that can be used to search for an icon
2803
- * with specific attributes.
2804
- *
2805
- * @param options Options for filtering which icon instances are considered a match.
2806
- * @returns A `HarnessPredicate` configured with the given options.
2807
- *
2808
- * @example
2809
- * ```typescript
2810
- * // Find icon by name
2811
- * const icon = await loader.getHarness(
2812
- * TnIconHarness.with({ name: 'home' })
2813
- * );
2814
- *
2815
- * // Find icon by library
2816
- * const customIcon = await loader.getHarness(
2817
- * TnIconHarness.with({ library: 'custom' })
2818
- * );
2819
- *
2820
- * // Find icon with specific size
2821
- * const largeIcon = await loader.getHarness(
2822
- * TnIconHarness.with({ size: 'lg' })
2823
- * );
2824
- * ```
2825
- */
2826
- static with(options = {}) {
2827
- return new HarnessPredicate(TnIconHarness, options)
2828
- .addOption('name', options.name, async (harness, name) => {
2829
- return (await harness.getName()) === name;
2830
- })
2831
- .addOption('library', options.library, async (harness, library) => {
2832
- return (await harness.getLibrary()) === library;
2833
- })
2834
- .addOption('size', options.size, async (harness, size) => {
2835
- return (await harness.getSize()) === size;
2836
- })
2837
- .addOption('fullSize', options.fullSize, async (harness, fullSize) => {
2838
- return (await harness.isFullSize()) === fullSize;
2839
- })
2840
- .addOption('customSize', options.customSize, async (harness, customSize) => {
2841
- return (await harness.getCustomSize()) === customSize;
2842
- });
2843
- }
2844
- /**
2845
- * Gets the icon name.
2846
- *
2847
- * @returns Promise resolving to the icon name.
2848
- *
2849
- * @example
2850
- * ```typescript
2851
- * const icon = await loader.getHarness(TnIconHarness);
2852
- * const name = await icon.getName();
2853
- * expect(name).toBe('folder');
2854
- * ```
2855
- */
2856
- async getName() {
2857
- const host = await this.host();
2858
- return host.getAttribute('name');
2859
- }
2860
- /**
2861
- * Gets the icon library.
2862
- *
2863
- * @returns Promise resolving to the icon library.
2864
- *
2865
- * @example
2866
- * ```typescript
2867
- * const icon = await loader.getHarness(TnIconHarness);
2868
- * const library = await icon.getLibrary();
2869
- * expect(library).toBe('mdi');
2870
- * ```
2871
- */
2872
- async getLibrary() {
2873
- const host = await this.host();
2874
- return host.getAttribute('library');
2875
- }
2876
- /**
2877
- * Gets the icon size.
2878
- *
2879
- * @returns Promise resolving to the icon size.
2880
- *
2881
- * @example
2882
- * ```typescript
2883
- * const icon = await loader.getHarness(TnIconHarness);
2884
- * const size = await icon.getSize();
2885
- * expect(size).toBe('lg');
2886
- * ```
2887
- */
2888
- async getSize() {
2889
- const host = await this.host();
2890
- return host.getAttribute('size');
2891
- }
2892
- /**
2893
- * Gets the icon color.
2894
- *
2895
- * @returns Promise resolving to the icon color.
2896
- *
2897
- * @example
2898
- * ```typescript
2899
- * const icon = await loader.getHarness(TnIconHarness);
2900
- * const color = await icon.getColor();
2901
- * expect(color).toBe('primary');
2902
- * ```
2903
- */
2904
- async getColor() {
2905
- const host = await this.host();
2906
- return host.getAttribute('color');
2907
- }
2908
- /**
2909
- * Checks if the icon is in full-size mode.
2910
- *
2911
- * @returns Promise resolving to true if the icon is full-size, false otherwise.
2912
- *
2913
- * @example
2914
- * ```typescript
2915
- * const icon = await loader.getHarness(TnIconHarness);
2916
- * const isFullSize = await icon.isFullSize();
2917
- * expect(isFullSize).toBe(true);
2918
- * ```
2919
- */
2920
- async isFullSize() {
2921
- const host = await this.host();
2922
- const fullSizeAttr = await host.getAttribute('full-size');
2923
- return fullSizeAttr === 'true';
2924
- }
2925
- /**
2926
- * Gets the icon custom size.
2927
- *
2928
- * @returns Promise resolving to the custom size value, or null if not set.
2929
- *
2930
- * @example
2931
- * ```typescript
2932
- * const icon = await loader.getHarness(TnIconHarness);
2933
- * const customSize = await icon.getCustomSize();
2934
- * expect(customSize).toBe('64px');
2935
- * ```
2936
- */
2937
- async getCustomSize() {
2938
- const host = await this.host();
2939
- return host.getAttribute('custom-size');
2940
- }
2941
- /**
2942
- * Checks if the icon is using a custom size.
2943
- *
2944
- * @returns Promise resolving to true if a custom size is set, false otherwise.
2945
- *
2946
- * @example
2947
- * ```typescript
2948
- * const icon = await loader.getHarness(TnIconHarness);
2949
- * const hasCustomSize = await icon.hasCustomSize();
2950
- * expect(hasCustomSize).toBe(true);
2951
- * ```
2952
- */
2953
- async hasCustomSize() {
2954
- const customSize = await this.getCustomSize();
2955
- return customSize !== null;
2956
- }
2957
- /**
2958
- * Clicks the icon.
2959
- *
2960
- * @returns Promise that resolves when the click action is complete.
2961
- *
2962
- * @example
2963
- * ```typescript
2964
- * const icon = await loader.getHarness(TnIconHarness.with({ name: 'close' }));
2965
- * await icon.click();
2966
- * ```
2967
- */
2968
- async click() {
2969
- const host = await this.host();
2970
- return host.click();
2971
- }
2972
- }
2973
-
2974
3175
  /**
2975
3176
  * Marks an icon name for inclusion in the TrueNAS UI sprite generation.
2976
3177
  *
@@ -8711,5 +8912,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
8711
8912
  * Generated bundle index. Do not edit.
8712
8913
  */
8713
8914
 
8714
- export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabPanelComponent, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
8915
+ export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabPanelComponent, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
8715
8916
  //# sourceMappingURL=truenas-ui-components.mjs.map