@truenas/ui-components 0.1.23 → 0.1.25
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.
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { inject, ElementRef, input, output, viewChild, signal, computed, effect, forwardRef, Component, ChangeDetectionStrategy, Injectable, ViewEncapsulation, Directive, contentChildren, ViewContainerRef, contentChild, ChangeDetectorRef, HostListener, TemplateRef, IterableDiffers, Pipe, model, afterNextRender, PLATFORM_ID, DestroyRef } from '@angular/core';
|
|
3
|
+
import * as i1$3 from '@angular/forms';
|
|
4
|
+
import { NG_VALUE_ACCESSOR, FormsModule, NgControl } from '@angular/forms';
|
|
5
|
+
import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
3
6
|
import * as i1$1 from '@angular/common';
|
|
4
7
|
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
5
8
|
import { mdiCheckCircle, mdiAlertCircle, mdiAlert, mdiInformation, mdiDotsVertical, mdiClose, mdiFolderOpen, mdiLock, mdiLoading, mdiFolderPlus, mdiFolderNetwork, mdiHarddisk, mdiDatabase, mdiFile, mdiFolder } from '@mdi/js';
|
|
@@ -7,11 +10,8 @@ import * as i1 from '@angular/platform-browser';
|
|
|
7
10
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
11
|
import { HttpClient } from '@angular/common/http';
|
|
9
12
|
import { firstValueFrom, BehaviorSubject, merge, Subject } from 'rxjs';
|
|
10
|
-
import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
11
13
|
import * as i1$4 from '@angular/cdk/a11y';
|
|
12
14
|
import { FocusMonitor, A11yModule } from '@angular/cdk/a11y';
|
|
13
|
-
import * as i1$3 from '@angular/forms';
|
|
14
|
-
import { FormsModule, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
15
15
|
import { Overlay, OverlayModule, OverlayPositionBuilder } from '@angular/cdk/overlay';
|
|
16
16
|
import { TemplatePortal, PortalModule, ComponentPortal } from '@angular/cdk/portal';
|
|
17
17
|
import { CdkMenu, CdkMenuItem, CdkMenuTrigger } from '@angular/cdk/menu';
|
|
@@ -26,6 +26,435 @@ import { DialogRef, DIALOG_DATA, Dialog } from '@angular/cdk/dialog';
|
|
|
26
26
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
|
27
27
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
28
28
|
|
|
29
|
+
let nextId = 0;
|
|
30
|
+
class TnAutocompleteComponent {
|
|
31
|
+
elementRef = inject(ElementRef);
|
|
32
|
+
/** Unique instance ID for ARIA linkage */
|
|
33
|
+
uid = `tn-autocomplete-${nextId++}`;
|
|
34
|
+
/** All available options */
|
|
35
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
36
|
+
/** Transform a value to its display string */
|
|
37
|
+
displayWith = input((v) => String(v), ...(ngDevMode ? [{ debugName: "displayWith" }] : []));
|
|
38
|
+
/** Placeholder text for the input */
|
|
39
|
+
placeholder = input('Type to search...', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
40
|
+
/** Whether the input is disabled */
|
|
41
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
42
|
+
/** Require the user to select from the dropdown — reverts on blur if no match */
|
|
43
|
+
requireSelection = input(false, ...(ngDevMode ? [{ debugName: "requireSelection" }] : []));
|
|
44
|
+
/** Custom filter function. Defaults to case-insensitive includes on displayWith text */
|
|
45
|
+
filterFn = input(undefined, ...(ngDevMode ? [{ debugName: "filterFn" }] : []));
|
|
46
|
+
/** Text shown when no options match the search */
|
|
47
|
+
noResultsText = input('No results found', ...(ngDevMode ? [{ debugName: "noResultsText" }] : []));
|
|
48
|
+
/** Maximum number of options to render */
|
|
49
|
+
maxResults = input(100, ...(ngDevMode ? [{ debugName: "maxResults" }] : []));
|
|
50
|
+
/** Test ID attribute */
|
|
51
|
+
testId = input('', ...(ngDevMode ? [{ debugName: "testId" }] : []));
|
|
52
|
+
/** Emits when an option is selected */
|
|
53
|
+
optionSelected = output();
|
|
54
|
+
/** Reference to the input element */
|
|
55
|
+
inputEl = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputEl" }] : []));
|
|
56
|
+
/** Current search term typed by the user */
|
|
57
|
+
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
58
|
+
/** Whether the dropdown is open */
|
|
59
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
60
|
+
/** Index of the currently highlighted option for keyboard nav */
|
|
61
|
+
highlightedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "highlightedIndex" }] : []));
|
|
62
|
+
/** The currently selected value */
|
|
63
|
+
selectedValue = signal(null, ...(ngDevMode ? [{ debugName: "selectedValue" }] : []));
|
|
64
|
+
/** CVA disabled state from the form */
|
|
65
|
+
formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : []));
|
|
66
|
+
/** Combined disabled state */
|
|
67
|
+
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
68
|
+
/** Filtered and capped options */
|
|
69
|
+
filteredOptions = computed(() => {
|
|
70
|
+
const term = this.searchTerm();
|
|
71
|
+
const all = this.options();
|
|
72
|
+
const customFilter = this.filterFn();
|
|
73
|
+
const display = this.displayWith();
|
|
74
|
+
const max = this.maxResults();
|
|
75
|
+
if (!term) {
|
|
76
|
+
return all.slice(0, max);
|
|
77
|
+
}
|
|
78
|
+
const lowerTerm = term.toLowerCase();
|
|
79
|
+
const filtered = customFilter
|
|
80
|
+
? all.filter((opt) => customFilter(opt, term))
|
|
81
|
+
: all.filter((opt) => display(opt).toLowerCase().includes(lowerTerm));
|
|
82
|
+
return filtered.slice(0, max);
|
|
83
|
+
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : []));
|
|
84
|
+
/** Whether there are any results to show */
|
|
85
|
+
hasResults = computed(() => this.filteredOptions().length > 0, ...(ngDevMode ? [{ debugName: "hasResults" }] : []));
|
|
86
|
+
onChange = (_value) => { };
|
|
87
|
+
onTouched = () => { };
|
|
88
|
+
constructor() {
|
|
89
|
+
// Click-outside detection
|
|
90
|
+
effect(() => {
|
|
91
|
+
if (this.isOpen()) {
|
|
92
|
+
const listener = (event) => {
|
|
93
|
+
if (!this.elementRef.nativeElement.contains(event.target)) {
|
|
94
|
+
this.close();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
document.addEventListener('click', listener);
|
|
99
|
+
}, 0);
|
|
100
|
+
return () => {
|
|
101
|
+
document.removeEventListener('click', listener);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// ── ControlValueAccessor ──
|
|
108
|
+
writeValue(value) {
|
|
109
|
+
this.selectedValue.set(value);
|
|
110
|
+
if (value !== null && value !== undefined) {
|
|
111
|
+
this.searchTerm.set(this.displayWith()(value));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.searchTerm.set('');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
registerOnChange(fn) {
|
|
118
|
+
this.onChange = fn;
|
|
119
|
+
}
|
|
120
|
+
registerOnTouched(fn) {
|
|
121
|
+
this.onTouched = fn;
|
|
122
|
+
}
|
|
123
|
+
setDisabledState(isDisabled) {
|
|
124
|
+
this.formDisabled.set(isDisabled);
|
|
125
|
+
}
|
|
126
|
+
// ── Event handlers ──
|
|
127
|
+
onInput(event) {
|
|
128
|
+
const value = event.target.value;
|
|
129
|
+
this.searchTerm.set(value);
|
|
130
|
+
this.highlightedIndex.set(-1);
|
|
131
|
+
if (!this.isOpen()) {
|
|
132
|
+
this.isOpen.set(true);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
onFocus() {
|
|
136
|
+
if (!this.isDisabled()) {
|
|
137
|
+
this.isOpen.set(true);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
onBlur() {
|
|
141
|
+
if (this.requireSelection()) {
|
|
142
|
+
const term = this.searchTerm();
|
|
143
|
+
const display = this.displayWith();
|
|
144
|
+
const match = this.options().find((opt) => display(opt).toLowerCase() === term.toLowerCase());
|
|
145
|
+
if (match) {
|
|
146
|
+
this.selectOption(match);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// Revert to last valid selection or clear
|
|
150
|
+
const current = this.selectedValue();
|
|
151
|
+
if (current !== null && current !== undefined) {
|
|
152
|
+
this.searchTerm.set(display(current));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.searchTerm.set('');
|
|
156
|
+
this.onChange(null);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.close();
|
|
161
|
+
this.onTouched();
|
|
162
|
+
}
|
|
163
|
+
onOptionClick(option) {
|
|
164
|
+
this.selectOption(option);
|
|
165
|
+
}
|
|
166
|
+
onKeydown(event) {
|
|
167
|
+
const options = this.filteredOptions();
|
|
168
|
+
switch (event.key) {
|
|
169
|
+
case 'ArrowDown':
|
|
170
|
+
event.preventDefault();
|
|
171
|
+
if (!this.isOpen()) {
|
|
172
|
+
this.isOpen.set(true);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.highlightedIndex.update((i) => i < options.length - 1 ? i + 1 : 0);
|
|
176
|
+
this.scrollToHighlighted();
|
|
177
|
+
}
|
|
178
|
+
break;
|
|
179
|
+
case 'ArrowUp':
|
|
180
|
+
event.preventDefault();
|
|
181
|
+
if (this.isOpen()) {
|
|
182
|
+
this.highlightedIndex.update((i) => i > 0 ? i - 1 : options.length - 1);
|
|
183
|
+
this.scrollToHighlighted();
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
case 'Enter':
|
|
187
|
+
event.preventDefault();
|
|
188
|
+
const idx = this.highlightedIndex();
|
|
189
|
+
if (this.isOpen() && idx >= 0 && idx < options.length) {
|
|
190
|
+
this.selectOption(options[idx]);
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case 'Escape':
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
this.close();
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ── Internal ──
|
|
200
|
+
selectOption(option) {
|
|
201
|
+
this.selectedValue.set(option);
|
|
202
|
+
this.searchTerm.set(this.displayWith()(option));
|
|
203
|
+
this.onChange(option);
|
|
204
|
+
this.optionSelected.emit(option);
|
|
205
|
+
this.close();
|
|
206
|
+
}
|
|
207
|
+
close() {
|
|
208
|
+
this.isOpen.set(false);
|
|
209
|
+
this.highlightedIndex.set(-1);
|
|
210
|
+
}
|
|
211
|
+
scrollToHighlighted() {
|
|
212
|
+
const idx = this.highlightedIndex();
|
|
213
|
+
const dropdown = this.elementRef.nativeElement.querySelector('.tn-autocomplete__dropdown');
|
|
214
|
+
const options = dropdown?.querySelectorAll('.tn-autocomplete__option');
|
|
215
|
+
if (options?.[idx]?.scrollIntoView) {
|
|
216
|
+
options[idx].scrollIntoView({ block: 'nearest' });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
220
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnAutocompleteComponent, isStandalone: true, selector: "tn-autocomplete", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, requireSelection: { classPropertyName: "requireSelection", publicName: "requireSelection", isSignal: true, isRequired: false, transformFunction: null }, filterFn: { classPropertyName: "filterFn", publicName: "filterFn", isSignal: true, isRequired: false, transformFunction: null }, noResultsText: { classPropertyName: "noResultsText", publicName: "noResultsText", isSignal: true, isRequired: false, transformFunction: null }, maxResults: { classPropertyName: "maxResults", publicName: "maxResults", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected" }, providers: [
|
|
221
|
+
{
|
|
222
|
+
provide: NG_VALUE_ACCESSOR,
|
|
223
|
+
useExisting: forwardRef(() => TnAutocompleteComponent),
|
|
224
|
+
multi: true,
|
|
225
|
+
},
|
|
226
|
+
], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-autocomplete\" [attr.data-testid]=\"testId()\">\n <input\n #inputEl\n type=\"text\"\n class=\"tn-autocomplete__input\"\n role=\"combobox\"\n autocomplete=\"off\"\n [class.open]=\"isOpen()\"\n [class.disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"searchTerm()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"isOpen() ? uid + '-dropdown' : null\"\n [attr.aria-activedescendant]=\"highlightedIndex() >= 0 ? uid + '-option-' + highlightedIndex() : null\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\" />\n\n @if (isOpen()) {\n <div\n class=\"tn-autocomplete__dropdown\"\n role=\"listbox\"\n [attr.id]=\"uid + '-dropdown'\">\n\n @if (hasResults()) {\n @for (option of filteredOptions(); track $index) {\n <div\n class=\"tn-autocomplete__option\"\n role=\"option\"\n tabindex=\"-1\"\n [class.highlighted]=\"highlightedIndex() === $index\"\n [attr.id]=\"uid + '-option-' + $index\"\n [attr.aria-selected]=\"highlightedIndex() === $index\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onOptionClick(option)\"\n (keydown.enter)=\"onOptionClick(option)\">\n {{ displayWith()(option) }}\n </div>\n }\n } @else {\n <div class=\"tn-autocomplete__no-results\">\n {{ noResultsText() }}\n </div>\n }\n </div>\n }\n</div>\n", styles: [".tn-autocomplete{position:relative;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-autocomplete__input{display:block;width:100%;min-height:2.5rem;padding:.5rem .75rem;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;color:var(--tn-fg1, #212529);font-size:.875rem;font-family:inherit;outline:none;box-sizing:border-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-autocomplete__input::placeholder{color:var(--tn-alt-fg1, #999)}.tn-autocomplete__input:hover:not(.disabled){border-color:var(--tn-primary, #007bff)}.tn-autocomplete__input:focus-visible,.tn-autocomplete__input.open{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px color-mix(in srgb,var(--tn-primary, #007bff) 25%,transparent)}.tn-autocomplete__input.disabled{background-color:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-fg2, #6c757d);cursor:not-allowed;opacity:.6}.tn-autocomplete__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:.25rem;background-color:var(--tn-bg2, #f5f5f5);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f;max-height:200px;overflow-y:auto;padding:.25rem 0}.tn-autocomplete__option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;color:var(--tn-fg1, #212529);transition:background-color .15s ease-in-out}.tn-autocomplete__option:hover{background-color:var(--tn-alt-bg2, #f8f9fa)}.tn-autocomplete__option.highlighted{background-color:var(--tn-alt-bg1, #f8f9fa)}.tn-autocomplete__no-results{padding:1rem .75rem;text-align:center;color:var(--tn-fg2, #6c757d);font-style:italic}@media(prefers-reduced-motion:reduce){.tn-autocomplete__input,.tn-autocomplete__option{transition:none}}\n"] });
|
|
227
|
+
}
|
|
228
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnAutocompleteComponent, decorators: [{
|
|
229
|
+
type: Component,
|
|
230
|
+
args: [{ selector: 'tn-autocomplete', standalone: true, imports: [], providers: [
|
|
231
|
+
{
|
|
232
|
+
provide: NG_VALUE_ACCESSOR,
|
|
233
|
+
useExisting: forwardRef(() => TnAutocompleteComponent),
|
|
234
|
+
multi: true,
|
|
235
|
+
},
|
|
236
|
+
], template: "<div class=\"tn-autocomplete\" [attr.data-testid]=\"testId()\">\n <input\n #inputEl\n type=\"text\"\n class=\"tn-autocomplete__input\"\n role=\"combobox\"\n autocomplete=\"off\"\n [class.open]=\"isOpen()\"\n [class.disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"searchTerm()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"isOpen() ? uid + '-dropdown' : null\"\n [attr.aria-activedescendant]=\"highlightedIndex() >= 0 ? uid + '-option-' + highlightedIndex() : null\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\" />\n\n @if (isOpen()) {\n <div\n class=\"tn-autocomplete__dropdown\"\n role=\"listbox\"\n [attr.id]=\"uid + '-dropdown'\">\n\n @if (hasResults()) {\n @for (option of filteredOptions(); track $index) {\n <div\n class=\"tn-autocomplete__option\"\n role=\"option\"\n tabindex=\"-1\"\n [class.highlighted]=\"highlightedIndex() === $index\"\n [attr.id]=\"uid + '-option-' + $index\"\n [attr.aria-selected]=\"highlightedIndex() === $index\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onOptionClick(option)\"\n (keydown.enter)=\"onOptionClick(option)\">\n {{ displayWith()(option) }}\n </div>\n }\n } @else {\n <div class=\"tn-autocomplete__no-results\">\n {{ noResultsText() }}\n </div>\n }\n </div>\n }\n</div>\n", styles: [".tn-autocomplete{position:relative;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif}.tn-autocomplete__input{display:block;width:100%;min-height:2.5rem;padding:.5rem .75rem;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;color:var(--tn-fg1, #212529);font-size:.875rem;font-family:inherit;outline:none;box-sizing:border-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-autocomplete__input::placeholder{color:var(--tn-alt-fg1, #999)}.tn-autocomplete__input:hover:not(.disabled){border-color:var(--tn-primary, #007bff)}.tn-autocomplete__input:focus-visible,.tn-autocomplete__input.open{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px color-mix(in srgb,var(--tn-primary, #007bff) 25%,transparent)}.tn-autocomplete__input.disabled{background-color:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-fg2, #6c757d);cursor:not-allowed;opacity:.6}.tn-autocomplete__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:.25rem;background-color:var(--tn-bg2, #f5f5f5);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f;max-height:200px;overflow-y:auto;padding:.25rem 0}.tn-autocomplete__option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;color:var(--tn-fg1, #212529);transition:background-color .15s ease-in-out}.tn-autocomplete__option:hover{background-color:var(--tn-alt-bg2, #f8f9fa)}.tn-autocomplete__option.highlighted{background-color:var(--tn-alt-bg1, #f8f9fa)}.tn-autocomplete__no-results{padding:1rem .75rem;text-align:center;color:var(--tn-fg2, #6c757d);font-style:italic}@media(prefers-reduced-motion:reduce){.tn-autocomplete__input,.tn-autocomplete__option{transition:none}}\n"] }]
|
|
237
|
+
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], requireSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireSelection", required: false }] }], filterFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterFn", required: false }] }], noResultsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsText", required: false }] }], maxResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxResults", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Harness for interacting with tn-autocomplete in tests.
|
|
241
|
+
* Provides methods for querying state, typing search text, and selecting options.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* // Find and select an option
|
|
246
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
247
|
+
* await ac.selectOption('United States');
|
|
248
|
+
*
|
|
249
|
+
* // Type to filter, then read options
|
|
250
|
+
* await ac.setInputValue('Can');
|
|
251
|
+
* const options = await ac.getOptions();
|
|
252
|
+
* expect(options).toEqual(['Canada']);
|
|
253
|
+
*
|
|
254
|
+
* // Filter by placeholder
|
|
255
|
+
* const countryAc = await loader.getHarness(
|
|
256
|
+
* TnAutocompleteHarness.with({ placeholder: 'Search countries...' })
|
|
257
|
+
* );
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
class TnAutocompleteHarness extends ComponentHarness {
|
|
261
|
+
/**
|
|
262
|
+
* The selector for the host element of a `TnAutocompleteComponent` instance.
|
|
263
|
+
*/
|
|
264
|
+
static hostSelector = 'tn-autocomplete';
|
|
265
|
+
_input = this.locatorFor('.tn-autocomplete__input');
|
|
266
|
+
/**
|
|
267
|
+
* Gets a `HarnessPredicate` that can be used to search for an autocomplete
|
|
268
|
+
* with specific attributes.
|
|
269
|
+
*
|
|
270
|
+
* @param options Options for filtering which autocomplete instances are considered a match.
|
|
271
|
+
* @returns A `HarnessPredicate` configured with the given options.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* // Find by exact placeholder
|
|
276
|
+
* const ac = await loader.getHarness(
|
|
277
|
+
* TnAutocompleteHarness.with({ placeholder: 'Search countries...' })
|
|
278
|
+
* );
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
static with(options = {}) {
|
|
282
|
+
return new HarnessPredicate(TnAutocompleteHarness, options)
|
|
283
|
+
.addOption('placeholder', options.placeholder, async (harness, placeholder) => {
|
|
284
|
+
return (await harness.getPlaceholder()) === placeholder;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Gets the current value of the input field.
|
|
289
|
+
*
|
|
290
|
+
* @returns Promise resolving to the input value.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
295
|
+
* await ac.selectOption('Canada');
|
|
296
|
+
* expect(await ac.getInputValue()).toBe('Canada');
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
async getInputValue() {
|
|
300
|
+
const input = await this._input();
|
|
301
|
+
return (await input.getProperty('value')) ?? '';
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Sets the value of the input by clearing and typing.
|
|
305
|
+
* This triggers filtering of the dropdown options.
|
|
306
|
+
*
|
|
307
|
+
* @param value The text to type into the input.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```typescript
|
|
311
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
312
|
+
* await ac.setInputValue('Can');
|
|
313
|
+
* const options = await ac.getOptions();
|
|
314
|
+
* expect(options).toEqual(['Canada']);
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
async setInputValue(value) {
|
|
318
|
+
const input = await this._input();
|
|
319
|
+
await input.clear();
|
|
320
|
+
await input.sendKeys(value);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Gets the placeholder text of the input.
|
|
324
|
+
*
|
|
325
|
+
* @returns Promise resolving to the placeholder string, or null.
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```typescript
|
|
329
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
330
|
+
* expect(await ac.getPlaceholder()).toBe('Type to search...');
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
async getPlaceholder() {
|
|
334
|
+
const input = await this._input();
|
|
335
|
+
return input.getAttribute('placeholder');
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Checks whether the dropdown is currently open.
|
|
339
|
+
*
|
|
340
|
+
* @returns Promise resolving to true if the dropdown is visible.
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```typescript
|
|
344
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
345
|
+
* expect(await ac.isOpen()).toBe(false);
|
|
346
|
+
* await ac.focus();
|
|
347
|
+
* expect(await ac.isOpen()).toBe(true);
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
async isOpen() {
|
|
351
|
+
const dropdown = await this.locatorForOptional('.tn-autocomplete__dropdown')();
|
|
352
|
+
return dropdown !== null;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Checks whether the autocomplete input is disabled.
|
|
356
|
+
*
|
|
357
|
+
* @returns Promise resolving to true if the input is disabled.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```typescript
|
|
361
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
362
|
+
* expect(await ac.isDisabled()).toBe(false);
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
async isDisabled() {
|
|
366
|
+
const input = await this._input();
|
|
367
|
+
return (await input.getProperty('disabled')) ?? false;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Gets the labels of all visible options in the dropdown.
|
|
371
|
+
* Opens the dropdown via focus if not already open.
|
|
372
|
+
*
|
|
373
|
+
* @returns Promise resolving to an array of option label strings.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```typescript
|
|
377
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
378
|
+
* await ac.setInputValue('C');
|
|
379
|
+
* const options = await ac.getOptions();
|
|
380
|
+
* expect(options).toContain('Canada');
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
async getOptions() {
|
|
384
|
+
const options = await this.locatorForAll('.tn-autocomplete__option')();
|
|
385
|
+
const labels = [];
|
|
386
|
+
for (const option of options) {
|
|
387
|
+
labels.push((await option.text()).trim());
|
|
388
|
+
}
|
|
389
|
+
return labels;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Selects an option by its label text. Opens the dropdown via focus if needed.
|
|
393
|
+
*
|
|
394
|
+
* @param filter The text to match against option labels. Supports string or RegExp.
|
|
395
|
+
* @returns Promise that resolves when the option has been selected.
|
|
396
|
+
* @throws Error if no matching option is found.
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
401
|
+
*
|
|
402
|
+
* // Select by exact text
|
|
403
|
+
* await ac.selectOption('Canada');
|
|
404
|
+
*
|
|
405
|
+
* // Select by regex
|
|
406
|
+
* await ac.selectOption(/united/i);
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
async selectOption(filter) {
|
|
410
|
+
const input = await this._input();
|
|
411
|
+
await input.focus();
|
|
412
|
+
const options = await this.locatorForAll('.tn-autocomplete__option')();
|
|
413
|
+
for (const option of options) {
|
|
414
|
+
const text = (await option.text()).trim();
|
|
415
|
+
const matches = filter instanceof RegExp ? filter.test(text) : text === filter;
|
|
416
|
+
if (matches) {
|
|
417
|
+
await option.click();
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
throw new Error(`Could not find autocomplete option matching "${filter}"`);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Focuses the autocomplete input, which opens the dropdown.
|
|
425
|
+
*
|
|
426
|
+
* @returns Promise that resolves when the input is focused.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
431
|
+
* await ac.focus();
|
|
432
|
+
* expect(await ac.isOpen()).toBe(true);
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
async focus() {
|
|
436
|
+
const input = await this._input();
|
|
437
|
+
return input.focus();
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Blurs the autocomplete input, which closes the dropdown.
|
|
441
|
+
*
|
|
442
|
+
* @returns Promise that resolves when the input is blurred.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* const ac = await loader.getHarness(TnAutocompleteHarness);
|
|
447
|
+
* await ac.focus();
|
|
448
|
+
* await ac.blur();
|
|
449
|
+
* expect(await ac.isOpen()).toBe(false);
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
452
|
+
async blur() {
|
|
453
|
+
const input = await this._input();
|
|
454
|
+
return input.blur();
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
29
458
|
var DiskType;
|
|
30
459
|
(function (DiskType) {
|
|
31
460
|
DiskType["Hdd"] = "HDD";
|
|
@@ -2163,6 +2592,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
2163
2592
|
args: [{ selector: 'tn-expansion-panel', standalone: true, imports: [CommonModule], animations: [expandCollapseAnimation], template: "<div [ngClass]=\"classes()\">\n <button class=\"tn-expansion-panel__header\"\n [disabled]=\"disabled()\"\n [attr.aria-expanded]=\"effectiveExpanded()\"\n [attr.aria-controls]=\"contentId\"\n [attr.aria-disabled]=\"disabled()\"\n (click)=\"toggle()\">\n @if (title()) {\n <div class=\"tn-expansion-panel__title\">\n {{ title() }}\n </div>\n }\n <ng-content select=\"[slot=title]\" />\n\n <div class=\"tn-expansion-panel__indicator\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n </div>\n </button>\n\n <div class=\"tn-expansion-panel__content\"\n [id]=\"contentId\"\n [attr.aria-hidden]=\"!effectiveExpanded()\"\n [@expandCollapse]=\"effectiveExpanded() ? 'expanded' : 'collapsed'\">\n <ng-content />\n </div>\n</div>", styles: [".tn-expansion-panel{border-radius:8px;transition:box-shadow .3s ease;overflow:hidden}.tn-expansion-panel--elevation-none{box-shadow:none}.tn-expansion-panel--elevation-low{box-shadow:0 1px 3px #0000001a}.tn-expansion-panel--elevation-medium{box-shadow:0 4px 6px #0000001a}.tn-expansion-panel--elevation-high{box-shadow:0 10px 15px #0000001a}.tn-expansion-panel--bordered{border:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel--background{background-color:var(--tn-bg2, #ffffff)}.tn-expansion-panel--disabled{opacity:.6;cursor:not-allowed}.tn-expansion-panel--disabled .tn-expansion-panel__header{cursor:not-allowed}.tn-expansion-panel--expanded .tn-expansion-panel__indicator svg{transform:rotate(180deg)}.tn-expansion-panel--padding-small .tn-expansion-panel__header{padding:12px 16px}.tn-expansion-panel--padding-small .tn-expansion-panel__content{padding:0 16px 16px}.tn-expansion-panel--padding-medium .tn-expansion-panel__header{padding:16px 24px}.tn-expansion-panel--padding-medium .tn-expansion-panel__content{padding:0 24px 24px}.tn-expansion-panel--padding-large .tn-expansion-panel__header{padding:24px 32px}.tn-expansion-panel--padding-large .tn-expansion-panel__content{padding:0 32px 32px}.tn-expansion-panel--title-header .tn-expansion-panel__title{font-size:1.125rem;font-weight:600;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-header .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-link .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-primary, #3b82f6);text-decoration:none}.tn-expansion-panel--title-link .tn-expansion-panel__indicator{color:var(--tn-primary, #3b82f6)}.tn-expansion-panel--title-link .tn-expansion-panel__header:hover:not(:disabled) .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel--title-link .tn-expansion-panel__header:focus .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel__header{width:100%;background:none;border:none;display:flex;align-items:center;justify-content:space-between;cursor:pointer;font-family:inherit;text-align:left;transition:background-color .2s ease}.tn-expansion-panel--bordered .tn-expansion-panel__header,.tn-expansion-panel--bordered.tn-expansion-panel--expanded .tn-expansion-panel__header{border-bottom:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel__header:hover:not(:disabled){background-color:var(--tn-alt-bg1, rgba(0, 0, 0, .05))}.tn-expansion-panel__header:focus{outline:2px solid var(--tn-primary, #3b82f6);outline-offset:-2px}.tn-expansion-panel__header:disabled{cursor:not-allowed}.tn-expansion-panel__title{margin:0;line-height:1.5;flex:1;transition:text-decoration .2s ease}.tn-expansion-panel__indicator{display:flex;align-items:center;justify-content:center;margin-left:16px;transition:transform .2s ease,color .2s ease}.tn-expansion-panel__indicator svg{transition:transform .2s ease}.tn-expansion-panel__content{overflow:hidden}.tn-expansion-panel__content:not(.tn-expansion-panel--expanded){border-bottom:none}\n"] }]
|
|
2164
2593
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], elevation: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevation", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], titleStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleStyle", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], toggleEvent: [{ type: i0.Output, args: ["toggleEvent"] }] } });
|
|
2165
2594
|
|
|
2595
|
+
/**
|
|
2596
|
+
* Directive to mark content for projection into the checkbox label area.
|
|
2597
|
+
* Use when the label needs rich content (links, icons, etc.) instead of plain text.
|
|
2598
|
+
*
|
|
2599
|
+
* @example
|
|
2600
|
+
* ```html
|
|
2601
|
+
* <tn-checkbox formControlName="terms">
|
|
2602
|
+
* <span tnCheckboxLabel>I agree to the <a href="/terms">Terms</a></span>
|
|
2603
|
+
* </tn-checkbox>
|
|
2604
|
+
* ```
|
|
2605
|
+
*/
|
|
2606
|
+
class TnCheckboxLabelDirective {
|
|
2607
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnCheckboxLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2608
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnCheckboxLabelDirective, isStandalone: true, selector: "[tnCheckboxLabel]", ngImport: i0 });
|
|
2609
|
+
}
|
|
2610
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnCheckboxLabelDirective, decorators: [{
|
|
2611
|
+
type: Directive,
|
|
2612
|
+
args: [{
|
|
2613
|
+
selector: '[tnCheckboxLabel]',
|
|
2614
|
+
standalone: true,
|
|
2615
|
+
}]
|
|
2616
|
+
}] });
|
|
2166
2617
|
class TnCheckboxComponent {
|
|
2167
2618
|
checkboxEl = viewChild.required('checkboxEl');
|
|
2168
2619
|
label = input('Checkbox', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
@@ -2174,9 +2625,12 @@ class TnCheckboxComponent {
|
|
|
2174
2625
|
error = input(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
2175
2626
|
checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
2176
2627
|
change = output();
|
|
2628
|
+
labelContent = contentChildren(TnCheckboxLabelDirective, ...(ngDevMode ? [{ debugName: "labelContent" }] : []));
|
|
2629
|
+
hasProjectedLabel = computed(() => this.labelContent().length > 0, ...(ngDevMode ? [{ debugName: "hasProjectedLabel" }] : []));
|
|
2177
2630
|
id = `tn-checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
2178
2631
|
// Internal state for CVA
|
|
2179
2632
|
internalChecked = signal(false, ...(ngDevMode ? [{ debugName: "internalChecked" }] : []));
|
|
2633
|
+
cvaControlled = signal(false, ...(ngDevMode ? [{ debugName: "cvaControlled" }] : []));
|
|
2180
2634
|
// CVA disabled state management
|
|
2181
2635
|
formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : []));
|
|
2182
2636
|
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
@@ -2198,10 +2652,11 @@ class TnCheckboxComponent {
|
|
|
2198
2652
|
this.focusMonitor.stopMonitoring(checkboxEl);
|
|
2199
2653
|
}
|
|
2200
2654
|
}
|
|
2201
|
-
//
|
|
2202
|
-
effectiveChecked = computed(() => this.internalChecked()
|
|
2655
|
+
// CVA takes precedence once a form control has written a value
|
|
2656
|
+
effectiveChecked = computed(() => this.cvaControlled() ? this.internalChecked() : this.checked(), ...(ngDevMode ? [{ debugName: "effectiveChecked" }] : []));
|
|
2203
2657
|
// ControlValueAccessor implementation
|
|
2204
2658
|
writeValue(value) {
|
|
2659
|
+
this.cvaControlled.set(true);
|
|
2205
2660
|
this.internalChecked.set(value !== null && value !== undefined ? value : false);
|
|
2206
2661
|
}
|
|
2207
2662
|
registerOnChange(fn) {
|
|
@@ -2241,7 +2696,7 @@ class TnCheckboxComponent {
|
|
|
2241
2696
|
useExisting: forwardRef(() => TnCheckboxComponent),
|
|
2242
2697
|
multi: true
|
|
2243
2698
|
}
|
|
2244
|
-
], viewQueries: [{ propertyName: "checkboxEl", first: true, predicate: ["checkboxEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [ngClass]=\"classes()\">\n <label class=\"tn-checkbox__label\" [for]=\"id\">\n <input\n #checkboxEl\n type=\"checkbox\"\n class=\"tn-checkbox__input\"\n [id]=\"id\"\n [checked]=\"effectiveChecked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.data-testid]=\"testId()\"\n [attr.aria-describedby]=\"error() ? id + '-error' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n (change)=\"onCheckboxChange($event)\"\n />\n <span class=\"tn-checkbox__checkmark\"></span>\n @if (!hideLabel()) {\n <span class=\"tn-checkbox__text\"
|
|
2699
|
+
], queries: [{ propertyName: "labelContent", predicate: TnCheckboxLabelDirective, isSignal: true }], viewQueries: [{ propertyName: "checkboxEl", first: true, predicate: ["checkboxEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [ngClass]=\"classes()\">\n <label class=\"tn-checkbox__label\" [for]=\"id\">\n <input\n #checkboxEl\n type=\"checkbox\"\n class=\"tn-checkbox__input\"\n [id]=\"id\"\n [checked]=\"effectiveChecked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.data-testid]=\"testId()\"\n [attr.aria-label]=\"hasProjectedLabel() ? label() : null\"\n [attr.aria-describedby]=\"error() ? id + '-error' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n (change)=\"onCheckboxChange($event)\"\n />\n <span class=\"tn-checkbox__checkmark\"></span>\n @if (!hideLabel()) {\n <span class=\"tn-checkbox__text\">\n @if (hasProjectedLabel()) {\n <ng-content select=\"[tnCheckboxLabel]\" />\n } @else {\n {{ label() }}\n }\n </span>\n }\n </label>\n\n @if (error()) {\n <div\n class=\"tn-checkbox__error\"\n role=\"alert\"\n aria-live=\"polite\"\n [id]=\"id + '-error'\"\n >\n {{ error() }}\n </div>\n }\n</div>", styles: [".tn-checkbox{display:flex;flex-direction:column;gap:4px}.tn-checkbox__label{display:flex;align-items:center;gap:8px;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--tn-font-family-body, \"Inter\", sans-serif);font-size:14px;line-height:1.5;color:var(--tn-fg1, #333)}.tn-checkbox__label:hover:not(.tn-checkbox--disabled) .tn-checkbox__checkmark{border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.tn-checkbox__input:checked~.tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:checked~.tn-checkbox__checkmark:after{display:block}.tn-checkbox__input:indeterminate~.tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:indeterminate~.tn-checkbox__checkmark:after{display:block;content:\"\";left:4px;top:8px;width:8px;height:2px;background:var(--tn-primary-txt, #fff);border-radius:1px;transform:none}.tn-checkbox__input:focus~.tn-checkbox__checkmark{outline:2px solid var(--tn-primary, #0095d5);outline-offset:2px}.tn-checkbox__input:disabled~.tn-checkbox__checkmark{background-color:var(--tn-bg2, #f5f5f5);border-color:var(--tn-lines, #e0e0e0);cursor:not-allowed}.tn-checkbox__input:disabled:checked~.tn-checkbox__checkmark{background-color:var(--tn-lines, #e0e0e0);border-color:var(--tn-lines, #e0e0e0)}.tn-checkbox__checkmark{position:relative;height:16px;width:16px;background-color:var(--tn-bg1, #fff);border:1px solid var(--tn-lines, #ccc);border-radius:2px;transition:all .2s ease;flex-shrink:0}.tn-checkbox__checkmark:after{content:\"\";position:absolute;display:none;left:5px;top:2px;width:4px;height:8px;border:solid var(--tn-primary-txt, #fff);border-width:0 2px 2px 0;transform:rotate(45deg)}.tn-checkbox__text{flex:1;min-width:0}.tn-checkbox__error{color:var(--tn-red, #dc2626);font-size:12px;font-family:var(--tn-font-family-body, \"Inter\", sans-serif);margin-top:4px;display:flex;align-items:center;gap:4px}.tn-checkbox--disabled .tn-checkbox__label{cursor:not-allowed;color:var(--tn-fg2, #666);opacity:.6}.tn-checkbox--disabled .tn-checkbox__text{color:var(--tn-fg2, #666)}.tn-checkbox--error .tn-checkbox__checkmark{border-color:var(--tn-red, #dc2626)}.tn-checkbox--indeterminate .tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:focus-visible~.tn-checkbox__checkmark{outline:2px solid var(--tn-primary, #0095d5);outline-offset:2px}@media(prefers-contrast:high){.tn-checkbox__checkmark{border-width:2px}}@media(prefers-reduced-motion:reduce){.tn-checkbox__checkmark{transition:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }] });
|
|
2245
2700
|
}
|
|
2246
2701
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnCheckboxComponent, decorators: [{
|
|
2247
2702
|
type: Component,
|
|
@@ -2251,8 +2706,212 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
2251
2706
|
useExisting: forwardRef(() => TnCheckboxComponent),
|
|
2252
2707
|
multi: true
|
|
2253
2708
|
}
|
|
2254
|
-
], template: "<div [ngClass]=\"classes()\">\n <label class=\"tn-checkbox__label\" [for]=\"id\">\n <input\n #checkboxEl\n type=\"checkbox\"\n class=\"tn-checkbox__input\"\n [id]=\"id\"\n [checked]=\"effectiveChecked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.data-testid]=\"testId()\"\n [attr.aria-describedby]=\"error() ? id + '-error' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n (change)=\"onCheckboxChange($event)\"\n />\n <span class=\"tn-checkbox__checkmark\"></span>\n @if (!hideLabel()) {\n <span class=\"tn-checkbox__text\"
|
|
2255
|
-
}], propDecorators: { checkboxEl: [{ type: i0.ViewChild, args: ['checkboxEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], change: [{ type: i0.Output, args: ["change"] }] } });
|
|
2709
|
+
], template: "<div [ngClass]=\"classes()\">\n <label class=\"tn-checkbox__label\" [for]=\"id\">\n <input\n #checkboxEl\n type=\"checkbox\"\n class=\"tn-checkbox__input\"\n [id]=\"id\"\n [checked]=\"effectiveChecked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.data-testid]=\"testId()\"\n [attr.aria-label]=\"hasProjectedLabel() ? label() : null\"\n [attr.aria-describedby]=\"error() ? id + '-error' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n (change)=\"onCheckboxChange($event)\"\n />\n <span class=\"tn-checkbox__checkmark\"></span>\n @if (!hideLabel()) {\n <span class=\"tn-checkbox__text\">\n @if (hasProjectedLabel()) {\n <ng-content select=\"[tnCheckboxLabel]\" />\n } @else {\n {{ label() }}\n }\n </span>\n }\n </label>\n\n @if (error()) {\n <div\n class=\"tn-checkbox__error\"\n role=\"alert\"\n aria-live=\"polite\"\n [id]=\"id + '-error'\"\n >\n {{ error() }}\n </div>\n }\n</div>", styles: [".tn-checkbox{display:flex;flex-direction:column;gap:4px}.tn-checkbox__label{display:flex;align-items:center;gap:8px;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--tn-font-family-body, \"Inter\", sans-serif);font-size:14px;line-height:1.5;color:var(--tn-fg1, #333)}.tn-checkbox__label:hover:not(.tn-checkbox--disabled) .tn-checkbox__checkmark{border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.tn-checkbox__input:checked~.tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:checked~.tn-checkbox__checkmark:after{display:block}.tn-checkbox__input:indeterminate~.tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:indeterminate~.tn-checkbox__checkmark:after{display:block;content:\"\";left:4px;top:8px;width:8px;height:2px;background:var(--tn-primary-txt, #fff);border-radius:1px;transform:none}.tn-checkbox__input:focus~.tn-checkbox__checkmark{outline:2px solid var(--tn-primary, #0095d5);outline-offset:2px}.tn-checkbox__input:disabled~.tn-checkbox__checkmark{background-color:var(--tn-bg2, #f5f5f5);border-color:var(--tn-lines, #e0e0e0);cursor:not-allowed}.tn-checkbox__input:disabled:checked~.tn-checkbox__checkmark{background-color:var(--tn-lines, #e0e0e0);border-color:var(--tn-lines, #e0e0e0)}.tn-checkbox__checkmark{position:relative;height:16px;width:16px;background-color:var(--tn-bg1, #fff);border:1px solid var(--tn-lines, #ccc);border-radius:2px;transition:all .2s ease;flex-shrink:0}.tn-checkbox__checkmark:after{content:\"\";position:absolute;display:none;left:5px;top:2px;width:4px;height:8px;border:solid var(--tn-primary-txt, #fff);border-width:0 2px 2px 0;transform:rotate(45deg)}.tn-checkbox__text{flex:1;min-width:0}.tn-checkbox__error{color:var(--tn-red, #dc2626);font-size:12px;font-family:var(--tn-font-family-body, \"Inter\", sans-serif);margin-top:4px;display:flex;align-items:center;gap:4px}.tn-checkbox--disabled .tn-checkbox__label{cursor:not-allowed;color:var(--tn-fg2, #666);opacity:.6}.tn-checkbox--disabled .tn-checkbox__text{color:var(--tn-fg2, #666)}.tn-checkbox--error .tn-checkbox__checkmark{border-color:var(--tn-red, #dc2626)}.tn-checkbox--indeterminate .tn-checkbox__checkmark{background-color:var(--tn-primary, #0095d5);border-color:var(--tn-primary, #0095d5)}.tn-checkbox__input:focus-visible~.tn-checkbox__checkmark{outline:2px solid var(--tn-primary, #0095d5);outline-offset:2px}@media(prefers-contrast:high){.tn-checkbox__checkmark{border-width:2px}}@media(prefers-reduced-motion:reduce){.tn-checkbox__checkmark{transition:none}}\n"] }]
|
|
2710
|
+
}], propDecorators: { checkboxEl: [{ type: i0.ViewChild, args: ['checkboxEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], labelContent: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnCheckboxLabelDirective), { isSignal: true }] }] } });
|
|
2711
|
+
|
|
2712
|
+
/**
|
|
2713
|
+
* Harness for interacting with tn-checkbox in tests.
|
|
2714
|
+
* Provides methods for checking, unchecking, and querying checkbox state.
|
|
2715
|
+
*
|
|
2716
|
+
* @example
|
|
2717
|
+
* ```typescript
|
|
2718
|
+
* // Find and check a checkbox
|
|
2719
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness.with({ label: 'Accept terms' }));
|
|
2720
|
+
* await checkbox.check();
|
|
2721
|
+
* expect(await checkbox.isChecked()).toBe(true);
|
|
2722
|
+
*
|
|
2723
|
+
* // Toggle a checkbox
|
|
2724
|
+
* await checkbox.toggle();
|
|
2725
|
+
* expect(await checkbox.isChecked()).toBe(false);
|
|
2726
|
+
*
|
|
2727
|
+
* // Find by testId
|
|
2728
|
+
* const terms = await loader.getHarness(TnCheckboxHarness.with({ testId: 'terms-checkbox' }));
|
|
2729
|
+
* ```
|
|
2730
|
+
*/
|
|
2731
|
+
class TnCheckboxHarness extends ComponentHarness {
|
|
2732
|
+
/**
|
|
2733
|
+
* The selector for the host element of a `TnCheckboxComponent` instance.
|
|
2734
|
+
*/
|
|
2735
|
+
static hostSelector = 'tn-checkbox';
|
|
2736
|
+
_input = this.locatorFor('.tn-checkbox__input');
|
|
2737
|
+
_label = this.locatorFor('.tn-checkbox__label');
|
|
2738
|
+
_text = this.locatorForOptional('.tn-checkbox__text');
|
|
2739
|
+
_error = this.locatorForOptional('.tn-checkbox__error');
|
|
2740
|
+
/**
|
|
2741
|
+
* Gets a `HarnessPredicate` that can be used to search for a checkbox
|
|
2742
|
+
* with specific attributes.
|
|
2743
|
+
*
|
|
2744
|
+
* @param options Options for filtering which checkbox instances are considered a match.
|
|
2745
|
+
* @returns A `HarnessPredicate` configured with the given options.
|
|
2746
|
+
*
|
|
2747
|
+
* @example
|
|
2748
|
+
* ```typescript
|
|
2749
|
+
* // Find by label text
|
|
2750
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness.with({ label: 'Accept' }));
|
|
2751
|
+
*
|
|
2752
|
+
* // Find by label regex
|
|
2753
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness.with({ label: /terms/i }));
|
|
2754
|
+
*
|
|
2755
|
+
* // Find by testId
|
|
2756
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness.with({ testId: 'my-checkbox' }));
|
|
2757
|
+
* ```
|
|
2758
|
+
*/
|
|
2759
|
+
static with(options = {}) {
|
|
2760
|
+
return new HarnessPredicate(TnCheckboxHarness, options)
|
|
2761
|
+
.addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabelText(), label))
|
|
2762
|
+
.addOption('testId', options.testId, async (harness, testId) => {
|
|
2763
|
+
return (await harness.getTestId()) === testId;
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Gets the checkbox label text content.
|
|
2768
|
+
*
|
|
2769
|
+
* @returns Promise resolving to the label text.
|
|
2770
|
+
*
|
|
2771
|
+
* @example
|
|
2772
|
+
* ```typescript
|
|
2773
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2774
|
+
* expect(await checkbox.getLabelText()).toBe('Accept terms');
|
|
2775
|
+
* ```
|
|
2776
|
+
*/
|
|
2777
|
+
async getLabelText() {
|
|
2778
|
+
const text = await this._text();
|
|
2779
|
+
return text ? (await text.text()).trim() : '';
|
|
2780
|
+
}
|
|
2781
|
+
/**
|
|
2782
|
+
* Checks whether the checkbox is currently checked.
|
|
2783
|
+
*
|
|
2784
|
+
* @returns Promise resolving to true if the checkbox is checked.
|
|
2785
|
+
*
|
|
2786
|
+
* @example
|
|
2787
|
+
* ```typescript
|
|
2788
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2789
|
+
* expect(await checkbox.isChecked()).toBe(false);
|
|
2790
|
+
* ```
|
|
2791
|
+
*/
|
|
2792
|
+
async isChecked() {
|
|
2793
|
+
const input = await this._input();
|
|
2794
|
+
return (await input.getProperty('checked')) ?? false;
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* Checks whether the checkbox is disabled.
|
|
2798
|
+
*
|
|
2799
|
+
* @returns Promise resolving to true if the checkbox is disabled.
|
|
2800
|
+
*
|
|
2801
|
+
* @example
|
|
2802
|
+
* ```typescript
|
|
2803
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2804
|
+
* expect(await checkbox.isDisabled()).toBe(false);
|
|
2805
|
+
* ```
|
|
2806
|
+
*/
|
|
2807
|
+
async isDisabled() {
|
|
2808
|
+
const input = await this._input();
|
|
2809
|
+
return (await input.getProperty('disabled')) ?? false;
|
|
2810
|
+
}
|
|
2811
|
+
/**
|
|
2812
|
+
* Checks whether the checkbox is required.
|
|
2813
|
+
*
|
|
2814
|
+
* @returns Promise resolving to true if the checkbox is required.
|
|
2815
|
+
*
|
|
2816
|
+
* @example
|
|
2817
|
+
* ```typescript
|
|
2818
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2819
|
+
* expect(await checkbox.isRequired()).toBe(true);
|
|
2820
|
+
* ```
|
|
2821
|
+
*/
|
|
2822
|
+
async isRequired() {
|
|
2823
|
+
const input = await this._input();
|
|
2824
|
+
return (await input.getProperty('required')) ?? false;
|
|
2825
|
+
}
|
|
2826
|
+
/**
|
|
2827
|
+
* Checks whether the checkbox is in the indeterminate state.
|
|
2828
|
+
*
|
|
2829
|
+
* @returns Promise resolving to true if the checkbox is indeterminate.
|
|
2830
|
+
*
|
|
2831
|
+
* @example
|
|
2832
|
+
* ```typescript
|
|
2833
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2834
|
+
* expect(await checkbox.isIndeterminate()).toBe(false);
|
|
2835
|
+
* ```
|
|
2836
|
+
*/
|
|
2837
|
+
async isIndeterminate() {
|
|
2838
|
+
const input = await this._input();
|
|
2839
|
+
return (await input.getProperty('indeterminate')) ?? false;
|
|
2840
|
+
}
|
|
2841
|
+
/**
|
|
2842
|
+
* Gets the test ID attribute value.
|
|
2843
|
+
*
|
|
2844
|
+
* @returns Promise resolving to the test ID string, or null.
|
|
2845
|
+
*
|
|
2846
|
+
* @example
|
|
2847
|
+
* ```typescript
|
|
2848
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2849
|
+
* expect(await checkbox.getTestId()).toBe('terms-checkbox');
|
|
2850
|
+
* ```
|
|
2851
|
+
*/
|
|
2852
|
+
async getTestId() {
|
|
2853
|
+
const input = await this._input();
|
|
2854
|
+
return input.getAttribute('data-testid');
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Gets the error message text, if any.
|
|
2858
|
+
*
|
|
2859
|
+
* @returns Promise resolving to the error message, or null if none.
|
|
2860
|
+
*
|
|
2861
|
+
* @example
|
|
2862
|
+
* ```typescript
|
|
2863
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2864
|
+
* expect(await checkbox.getErrorText()).toBe('You must accept the terms');
|
|
2865
|
+
* ```
|
|
2866
|
+
*/
|
|
2867
|
+
async getErrorText() {
|
|
2868
|
+
const error = await this._error();
|
|
2869
|
+
return error ? (await error.text()).trim() : null;
|
|
2870
|
+
}
|
|
2871
|
+
/**
|
|
2872
|
+
* Checks the checkbox. No-op if already checked.
|
|
2873
|
+
*
|
|
2874
|
+
* @example
|
|
2875
|
+
* ```typescript
|
|
2876
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2877
|
+
* await checkbox.check();
|
|
2878
|
+
* expect(await checkbox.isChecked()).toBe(true);
|
|
2879
|
+
* ```
|
|
2880
|
+
*/
|
|
2881
|
+
async check() {
|
|
2882
|
+
if (!(await this.isChecked())) {
|
|
2883
|
+
await this.toggle();
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Unchecks the checkbox. No-op if already unchecked.
|
|
2888
|
+
*
|
|
2889
|
+
* @example
|
|
2890
|
+
* ```typescript
|
|
2891
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2892
|
+
* await checkbox.uncheck();
|
|
2893
|
+
* expect(await checkbox.isChecked()).toBe(false);
|
|
2894
|
+
* ```
|
|
2895
|
+
*/
|
|
2896
|
+
async uncheck() {
|
|
2897
|
+
if (await this.isChecked()) {
|
|
2898
|
+
await this.toggle();
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Toggles the checkbox checked state by clicking the label.
|
|
2903
|
+
*
|
|
2904
|
+
* @example
|
|
2905
|
+
* ```typescript
|
|
2906
|
+
* const checkbox = await loader.getHarness(TnCheckboxHarness);
|
|
2907
|
+
* await checkbox.toggle();
|
|
2908
|
+
* ```
|
|
2909
|
+
*/
|
|
2910
|
+
async toggle() {
|
|
2911
|
+
const label = await this._label();
|
|
2912
|
+
await label.click();
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2256
2915
|
|
|
2257
2916
|
class TnRadioComponent {
|
|
2258
2917
|
radioEl = viewChild.required('radioEl');
|
|
@@ -9989,5 +10648,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
9989
10648
|
* Generated bundle index. Do not edit.
|
|
9990
10649
|
*/
|
|
9991
10650
|
|
|
9992
|
-
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, 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, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnEmptyComponent, TnEmptyHarness, 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, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
10651
|
+
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnEmptyComponent, TnEmptyHarness, 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, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
9993
10652
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|