@truenas/ui-components 0.1.14 → 0.1.16
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.
|
@@ -2306,15 +2306,15 @@ class TnTabComponent {
|
|
|
2306
2306
|
// Internal properties set by parent TnTabsComponent (public signals for parent control)
|
|
2307
2307
|
index = signal(0, ...(ngDevMode ? [{ debugName: "index" }] : []));
|
|
2308
2308
|
isActive = signal(false, ...(ngDevMode ? [{ debugName: "isActive" }] : []));
|
|
2309
|
-
tabsComponent;
|
|
2309
|
+
tabsComponent;
|
|
2310
2310
|
elementRef = inject((ElementRef));
|
|
2311
2311
|
hasIconContent = signal(false, ...(ngDevMode ? [{ debugName: "hasIconContent" }] : []));
|
|
2312
2312
|
ngAfterContentInit() {
|
|
2313
2313
|
this.hasIconContent.set(!!this.iconContent());
|
|
2314
2314
|
}
|
|
2315
2315
|
onClick() {
|
|
2316
|
-
if (!this.disabled()) {
|
|
2317
|
-
this.
|
|
2316
|
+
if (!this.disabled() && this.tabsComponent) {
|
|
2317
|
+
this.tabsComponent.selectTab(this.index());
|
|
2318
2318
|
}
|
|
2319
2319
|
}
|
|
2320
2320
|
onKeydown(event) {
|
|
@@ -2427,10 +2427,6 @@ class TnTabsComponent {
|
|
|
2427
2427
|
}
|
|
2428
2428
|
this.cdr.detectChanges();
|
|
2429
2429
|
});
|
|
2430
|
-
}
|
|
2431
|
-
ngAfterContentInit() {
|
|
2432
|
-
this.initializeTabs();
|
|
2433
|
-
this.selectTab(this.internalSelectedIndex());
|
|
2434
2430
|
// Listen for tab changes
|
|
2435
2431
|
effect(() => {
|
|
2436
2432
|
// Track tabs signal to react to changes
|
|
@@ -2441,6 +2437,10 @@ class TnTabsComponent {
|
|
|
2441
2437
|
}
|
|
2442
2438
|
});
|
|
2443
2439
|
}
|
|
2440
|
+
ngAfterContentInit() {
|
|
2441
|
+
this.initializeTabs();
|
|
2442
|
+
this.selectTab(this.internalSelectedIndex());
|
|
2443
|
+
}
|
|
2444
2444
|
ngAfterViewInit() {
|
|
2445
2445
|
// Wait for next tick to ensure DOM is fully rendered
|
|
2446
2446
|
setTimeout(() => {
|
|
@@ -2466,12 +2466,6 @@ class TnTabsComponent {
|
|
|
2466
2466
|
if (tab.elementRef) {
|
|
2467
2467
|
this.focusMonitor.monitor(tab.elementRef);
|
|
2468
2468
|
}
|
|
2469
|
-
// Set up click handlers
|
|
2470
|
-
tab.selected.subscribe(() => {
|
|
2471
|
-
if (!tab.disabled()) {
|
|
2472
|
-
this.selectTab(index);
|
|
2473
|
-
}
|
|
2474
|
-
});
|
|
2475
2469
|
});
|
|
2476
2470
|
this.panels().forEach((panel, index) => {
|
|
2477
2471
|
panel.index.set(index);
|
|
@@ -2666,6 +2660,409 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
2666
2660
|
args: [{ selector: 'tn-tabs', standalone: true, imports: [CommonModule, A11yModule, TnTabComponent, TnTabPanelComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div role=\"tablist\" [ngClass]=\"classes()\" [attr.aria-orientation]=\"orientation()\">\n <div #tabHeader class=\"tn-tabs__header\">\n <ng-content select=\"tn-tab\" />\n @if (highlightBarVisible()) {\n <div class=\"tn-tabs__highlight-bar\"\n [style.left.px]=\"highlightBarLeft()\"\n [style.width.px]=\"highlightBarWidth()\"\n [style.top.px]=\"highlightBarTop()\"\n [style.height.px]=\"highlightBarHeight()\">\n </div>\n }\n </div>\n\n <div class=\"tn-tabs__content\">\n <ng-content select=\"tn-tab-panel\" />\n </div>\n</div>", styles: [".tn-tabs{display:flex;flex-direction:column;width:100%;height:100%;min-width:0;font-family:var(--tn-font-family-body, \"Inter\", sans-serif)}.tn-tabs--disabled{opacity:.6;pointer-events:none}.tn-tabs--vertical{flex-direction:row}.tn-tabs--vertical .tn-tabs__header{flex-direction:column;border-bottom:none;border-right:1px solid var(--tn-lines, #e0e0e0);min-width:240px;width:auto}.tn-tabs--vertical .tn-tabs__content{flex:1;min-width:0}.tn-tabs--vertical .tn-tabs__highlight-bar{bottom:auto;height:auto}.tn-tabs--vertical .tn-tab{justify-content:flex-start;text-align:left;width:100%}.tn-tabs--vertical .tn-tab:hover:not(.tn-tab--disabled){background-color:var(--tn-alt-bg1, #f5f5f5);color:var(--tn-fg1, #333)}.tn-tabs__header{display:flex;background-color:var(--tn-bg1, #fff);position:relative;border-bottom:1px solid var(--tn-lines, #e0e0e0)}.tn-tabs__highlight-bar{position:absolute;bottom:-1px;height:2px;background-color:var(--tn-primary, #0095d5);transition:left .3s ease,width .3s ease,top .3s ease,height .3s ease;z-index:1}.tn-tabs__content{flex:1;position:relative;background-color:var(--tn-bg1, #fff);min-height:0;width:100%;overflow:hidden}@media(max-width:768px){.tn-tabs__header{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}.tn-tabs__header::-webkit-scrollbar{display:none}.tn-tabs--vertical .tn-tabs__header{overflow-y:auto;overflow-x:visible;max-height:300px}}@media(prefers-reduced-motion:reduce){.tn-tabs__highlight-bar{transition:none}}\n"] }]
|
|
2667
2661
|
}], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnTabComponent), { isSignal: true }] }], panels: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnTabPanelComponent), { isSignal: true }] }], tabHeader: [{ type: i0.ViewChild, args: ['tabHeader', { isSignal: true }] }], selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], highlightPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightPosition", required: false }] }], selectedIndexChange: [{ type: i0.Output, args: ["selectedIndexChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
|
|
2668
2662
|
|
|
2663
|
+
/**
|
|
2664
|
+
* Harness for interacting with tn-tab in tests.
|
|
2665
|
+
* Provides methods for querying individual tab state and simulating selection.
|
|
2666
|
+
*
|
|
2667
|
+
* @example
|
|
2668
|
+
* ```typescript
|
|
2669
|
+
* // Find a tab by label
|
|
2670
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: 'Settings' }));
|
|
2671
|
+
*
|
|
2672
|
+
* // Check if active
|
|
2673
|
+
* expect(await tab.isSelected()).toBe(false);
|
|
2674
|
+
*
|
|
2675
|
+
* // Select it
|
|
2676
|
+
* await tab.select();
|
|
2677
|
+
* expect(await tab.isSelected()).toBe(true);
|
|
2678
|
+
* ```
|
|
2679
|
+
*/
|
|
2680
|
+
class TnTabHarness extends ComponentHarness {
|
|
2681
|
+
/**
|
|
2682
|
+
* The selector for the host element of a `TnTabComponent` instance.
|
|
2683
|
+
*/
|
|
2684
|
+
static hostSelector = 'tn-tab';
|
|
2685
|
+
_button = this.locatorFor('button[role="tab"]');
|
|
2686
|
+
/**
|
|
2687
|
+
* Gets a `HarnessPredicate` that can be used to search for a tab
|
|
2688
|
+
* with specific attributes.
|
|
2689
|
+
*
|
|
2690
|
+
* @param options Options for filtering which tab instances are considered a match.
|
|
2691
|
+
* @returns A `HarnessPredicate` configured with the given options.
|
|
2692
|
+
*
|
|
2693
|
+
* @example
|
|
2694
|
+
* ```typescript
|
|
2695
|
+
* // Find tab by exact label
|
|
2696
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: 'Overview' }));
|
|
2697
|
+
*
|
|
2698
|
+
* // Find tab by regex
|
|
2699
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: /settings/i }));
|
|
2700
|
+
* ```
|
|
2701
|
+
*/
|
|
2702
|
+
static with(options = {}) {
|
|
2703
|
+
return new HarnessPredicate(TnTabHarness, options)
|
|
2704
|
+
.addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
2705
|
+
}
|
|
2706
|
+
/**
|
|
2707
|
+
* Gets the tab's label text.
|
|
2708
|
+
*
|
|
2709
|
+
* @returns Promise resolving to the tab's label string.
|
|
2710
|
+
*
|
|
2711
|
+
* @example
|
|
2712
|
+
* ```typescript
|
|
2713
|
+
* const tab = await loader.getHarness(TnTabHarness);
|
|
2714
|
+
* expect(await tab.getLabel()).toBe('Overview');
|
|
2715
|
+
* ```
|
|
2716
|
+
*/
|
|
2717
|
+
async getLabel() {
|
|
2718
|
+
const labelEl = await this.locatorFor('.tn-tab__label')();
|
|
2719
|
+
return (await labelEl.text()).trim();
|
|
2720
|
+
}
|
|
2721
|
+
/**
|
|
2722
|
+
* Checks whether the tab is currently selected (active).
|
|
2723
|
+
*
|
|
2724
|
+
* @returns Promise resolving to true if the tab is selected.
|
|
2725
|
+
*
|
|
2726
|
+
* @example
|
|
2727
|
+
* ```typescript
|
|
2728
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: 'Overview' }));
|
|
2729
|
+
* expect(await tab.isSelected()).toBe(true);
|
|
2730
|
+
* ```
|
|
2731
|
+
*/
|
|
2732
|
+
async isSelected() {
|
|
2733
|
+
const button = await this._button();
|
|
2734
|
+
return (await button.getAttribute('aria-selected')) === 'true';
|
|
2735
|
+
}
|
|
2736
|
+
/**
|
|
2737
|
+
* Checks whether the tab is disabled.
|
|
2738
|
+
*
|
|
2739
|
+
* @returns Promise resolving to true if the tab is disabled.
|
|
2740
|
+
*
|
|
2741
|
+
* @example
|
|
2742
|
+
* ```typescript
|
|
2743
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: 'Disabled Tab' }));
|
|
2744
|
+
* expect(await tab.isDisabled()).toBe(true);
|
|
2745
|
+
* ```
|
|
2746
|
+
*/
|
|
2747
|
+
async isDisabled() {
|
|
2748
|
+
const button = await this._button();
|
|
2749
|
+
return (await button.getProperty('disabled')) ?? false;
|
|
2750
|
+
}
|
|
2751
|
+
/**
|
|
2752
|
+
* Selects the tab by clicking it.
|
|
2753
|
+
*
|
|
2754
|
+
* @returns Promise that resolves when the tab has been clicked.
|
|
2755
|
+
*
|
|
2756
|
+
* @example
|
|
2757
|
+
* ```typescript
|
|
2758
|
+
* const tab = await loader.getHarness(TnTabHarness.with({ label: 'Settings' }));
|
|
2759
|
+
* await tab.select();
|
|
2760
|
+
* ```
|
|
2761
|
+
*/
|
|
2762
|
+
async select() {
|
|
2763
|
+
const button = await this._button();
|
|
2764
|
+
await button.click();
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Gets the tab's testId attribute value.
|
|
2768
|
+
*
|
|
2769
|
+
* @returns Promise resolving to the data-testid value, or null if not set.
|
|
2770
|
+
*
|
|
2771
|
+
* @example
|
|
2772
|
+
* ```typescript
|
|
2773
|
+
* const tab = await loader.getHarness(TnTabHarness);
|
|
2774
|
+
* expect(await tab.getTestId()).toBe('my-tab');
|
|
2775
|
+
* ```
|
|
2776
|
+
*/
|
|
2777
|
+
async getTestId() {
|
|
2778
|
+
const button = await this._button();
|
|
2779
|
+
return button.getAttribute('data-testid');
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
/**
|
|
2784
|
+
* Harness for interacting with tn-tab-panel in tests.
|
|
2785
|
+
* Provides methods for querying panel visibility and content.
|
|
2786
|
+
*
|
|
2787
|
+
* @example
|
|
2788
|
+
* ```typescript
|
|
2789
|
+
* // Get all panels
|
|
2790
|
+
* const panels = await loader.getAllHarnesses(TnTabPanelHarness);
|
|
2791
|
+
*
|
|
2792
|
+
* // Check which panel is active
|
|
2793
|
+
* for (const panel of panels) {
|
|
2794
|
+
* if (await panel.isActive()) {
|
|
2795
|
+
* const text = await panel.getTextContent();
|
|
2796
|
+
* expect(text).toContain('Overview');
|
|
2797
|
+
* }
|
|
2798
|
+
* }
|
|
2799
|
+
* ```
|
|
2800
|
+
*/
|
|
2801
|
+
class TnTabPanelHarness extends ComponentHarness {
|
|
2802
|
+
/**
|
|
2803
|
+
* The selector for the host element of a `TnTabPanelComponent` instance.
|
|
2804
|
+
*/
|
|
2805
|
+
static hostSelector = 'tn-tab-panel';
|
|
2806
|
+
_panel = this.locatorFor('[role="tabpanel"]');
|
|
2807
|
+
/**
|
|
2808
|
+
* Gets a `HarnessPredicate` that can be used to search for a tab panel
|
|
2809
|
+
* with specific attributes.
|
|
2810
|
+
*
|
|
2811
|
+
* @param options Options for filtering which panel instances are considered a match.
|
|
2812
|
+
* @returns A `HarnessPredicate` configured with the given options.
|
|
2813
|
+
*
|
|
2814
|
+
* @example
|
|
2815
|
+
* ```typescript
|
|
2816
|
+
* const panel = await loader.getHarness(
|
|
2817
|
+
* TnTabPanelHarness.with({ textContains: 'Overview' })
|
|
2818
|
+
* );
|
|
2819
|
+
* ```
|
|
2820
|
+
*/
|
|
2821
|
+
static with(options = {}) {
|
|
2822
|
+
return new HarnessPredicate(TnTabPanelHarness, options)
|
|
2823
|
+
.addOption('textContains', options.textContains, (harness, text) => HarnessPredicate.stringMatches(harness.getTextContent(), text));
|
|
2824
|
+
}
|
|
2825
|
+
/**
|
|
2826
|
+
* Checks whether the panel is currently active (visible).
|
|
2827
|
+
*
|
|
2828
|
+
* @returns Promise resolving to true if the panel is active.
|
|
2829
|
+
*
|
|
2830
|
+
* @example
|
|
2831
|
+
* ```typescript
|
|
2832
|
+
* const panel = await loader.getHarness(TnTabPanelHarness);
|
|
2833
|
+
* expect(await panel.isActive()).toBe(true);
|
|
2834
|
+
* ```
|
|
2835
|
+
*/
|
|
2836
|
+
async isActive() {
|
|
2837
|
+
const panel = await this._panel();
|
|
2838
|
+
return (await panel.getAttribute('aria-hidden')) === 'false';
|
|
2839
|
+
}
|
|
2840
|
+
/**
|
|
2841
|
+
* Gets the text content of the panel.
|
|
2842
|
+
*
|
|
2843
|
+
* @returns Promise resolving to the panel's text content.
|
|
2844
|
+
*
|
|
2845
|
+
* @example
|
|
2846
|
+
* ```typescript
|
|
2847
|
+
* const panel = await loader.getHarness(TnTabPanelHarness);
|
|
2848
|
+
* expect(await panel.getTextContent()).toContain('Overview');
|
|
2849
|
+
* ```
|
|
2850
|
+
*/
|
|
2851
|
+
async getTextContent() {
|
|
2852
|
+
const panel = await this._panel();
|
|
2853
|
+
return (await panel.text()).trim();
|
|
2854
|
+
}
|
|
2855
|
+
/**
|
|
2856
|
+
* Gets the panel's testId attribute value.
|
|
2857
|
+
*
|
|
2858
|
+
* @returns Promise resolving to the data-testid value, or null if not set.
|
|
2859
|
+
*
|
|
2860
|
+
* @example
|
|
2861
|
+
* ```typescript
|
|
2862
|
+
* const panel = await loader.getHarness(TnTabPanelHarness);
|
|
2863
|
+
* expect(await panel.getTestId()).toBe('my-panel');
|
|
2864
|
+
* ```
|
|
2865
|
+
*/
|
|
2866
|
+
async getTestId() {
|
|
2867
|
+
const panel = await this._panel();
|
|
2868
|
+
return panel.getAttribute('data-testid');
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
/**
|
|
2873
|
+
* Harness for interacting with tn-tabs in tests.
|
|
2874
|
+
* Provides methods for querying tab state, selecting tabs, and inspecting panels.
|
|
2875
|
+
*
|
|
2876
|
+
* @example
|
|
2877
|
+
* ```typescript
|
|
2878
|
+
* // Get the tabs harness
|
|
2879
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
2880
|
+
*
|
|
2881
|
+
* // Select a tab by label
|
|
2882
|
+
* await tabs.selectTab({ label: 'Settings' });
|
|
2883
|
+
*
|
|
2884
|
+
* // Get the selected tab label
|
|
2885
|
+
* const selected = await tabs.getSelectedTab();
|
|
2886
|
+
* expect(await selected.getLabel()).toBe('Settings');
|
|
2887
|
+
*
|
|
2888
|
+
* // Get all tab labels
|
|
2889
|
+
* const labels = await tabs.getTabLabels();
|
|
2890
|
+
* expect(labels).toEqual(['Overview', 'Details', 'Settings']);
|
|
2891
|
+
* ```
|
|
2892
|
+
*/
|
|
2893
|
+
class TnTabsHarness extends ComponentHarness {
|
|
2894
|
+
/**
|
|
2895
|
+
* The selector for the host element of a `TnTabsComponent` instance.
|
|
2896
|
+
*/
|
|
2897
|
+
static hostSelector = 'tn-tabs';
|
|
2898
|
+
/**
|
|
2899
|
+
* Gets a `HarnessPredicate` that can be used to search for tabs
|
|
2900
|
+
* with specific attributes.
|
|
2901
|
+
*
|
|
2902
|
+
* @param options Options for filtering which tabs instances are considered a match.
|
|
2903
|
+
* @returns A `HarnessPredicate` configured with the given options.
|
|
2904
|
+
*
|
|
2905
|
+
* @example
|
|
2906
|
+
* ```typescript
|
|
2907
|
+
* // Find by orientation
|
|
2908
|
+
* const tabs = await loader.getHarness(TnTabsHarness.with({ orientation: 'vertical' }));
|
|
2909
|
+
*
|
|
2910
|
+
* // Find the tab group containing a "Settings" tab
|
|
2911
|
+
* const tabs = await loader.getHarness(TnTabsHarness.with({ hasTab: 'Settings' }));
|
|
2912
|
+
*
|
|
2913
|
+
* // Find by regex
|
|
2914
|
+
* const tabs = await loader.getHarness(TnTabsHarness.with({ hasTab: /settings/i }));
|
|
2915
|
+
* ```
|
|
2916
|
+
*/
|
|
2917
|
+
static with(options = {}) {
|
|
2918
|
+
return new HarnessPredicate(TnTabsHarness, options)
|
|
2919
|
+
.addOption('orientation', options.orientation, async (harness, orientation) => {
|
|
2920
|
+
return (await harness.getOrientation()) === orientation;
|
|
2921
|
+
})
|
|
2922
|
+
.addOption('hasTab', options.hasTab, async (harness, label) => {
|
|
2923
|
+
const labels = await harness.getTabLabels();
|
|
2924
|
+
if (label instanceof RegExp) {
|
|
2925
|
+
return labels.some(l => label.test(l));
|
|
2926
|
+
}
|
|
2927
|
+
return labels.includes(label);
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* Gets all tab harnesses within this tab group.
|
|
2932
|
+
*
|
|
2933
|
+
* @returns Promise resolving to an array of `TnTabHarness` instances.
|
|
2934
|
+
*
|
|
2935
|
+
* @example
|
|
2936
|
+
* ```typescript
|
|
2937
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
2938
|
+
* const allTabs = await tabs.getTabs();
|
|
2939
|
+
* expect(allTabs.length).toBe(3);
|
|
2940
|
+
* ```
|
|
2941
|
+
*/
|
|
2942
|
+
async getTabs() {
|
|
2943
|
+
return this.locatorForAll(TnTabHarness)();
|
|
2944
|
+
}
|
|
2945
|
+
/**
|
|
2946
|
+
* Gets a specific tab by filter criteria.
|
|
2947
|
+
*
|
|
2948
|
+
* @param filter Optional filter to match a specific tab.
|
|
2949
|
+
* @returns Promise resolving to the matching `TnTabHarness`.
|
|
2950
|
+
*
|
|
2951
|
+
* @example
|
|
2952
|
+
* ```typescript
|
|
2953
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
2954
|
+
* const settingsTab = await tabs.getTab({ label: 'Settings' });
|
|
2955
|
+
* ```
|
|
2956
|
+
*/
|
|
2957
|
+
async getTab(filter = {}) {
|
|
2958
|
+
return this.locatorFor(TnTabHarness.with(filter))();
|
|
2959
|
+
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Gets all panel harnesses within this tab group.
|
|
2962
|
+
*
|
|
2963
|
+
* @returns Promise resolving to an array of `TnTabPanelHarness` instances.
|
|
2964
|
+
*
|
|
2965
|
+
* @example
|
|
2966
|
+
* ```typescript
|
|
2967
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
2968
|
+
* const panels = await tabs.getPanels();
|
|
2969
|
+
* expect(panels.length).toBe(3);
|
|
2970
|
+
* ```
|
|
2971
|
+
*/
|
|
2972
|
+
async getPanels() {
|
|
2973
|
+
return this.locatorForAll(TnTabPanelHarness)();
|
|
2974
|
+
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Gets all tab labels as strings.
|
|
2977
|
+
*
|
|
2978
|
+
* @returns Promise resolving to an array of tab label strings.
|
|
2979
|
+
*
|
|
2980
|
+
* @example
|
|
2981
|
+
* ```typescript
|
|
2982
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
2983
|
+
* const labels = await tabs.getTabLabels();
|
|
2984
|
+
* expect(labels).toEqual(['Overview', 'Details', 'Settings']);
|
|
2985
|
+
* ```
|
|
2986
|
+
*/
|
|
2987
|
+
async getTabLabels() {
|
|
2988
|
+
const tabs = await this.getTabs();
|
|
2989
|
+
return Promise.all(tabs.map(tab => tab.getLabel()));
|
|
2990
|
+
}
|
|
2991
|
+
/**
|
|
2992
|
+
* Gets the currently selected (active) tab.
|
|
2993
|
+
*
|
|
2994
|
+
* @returns Promise resolving to the active `TnTabHarness`.
|
|
2995
|
+
* @throws If no active tab is found.
|
|
2996
|
+
*
|
|
2997
|
+
* @example
|
|
2998
|
+
* ```typescript
|
|
2999
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
3000
|
+
* const selected = await tabs.getSelectedTab();
|
|
3001
|
+
* expect(await selected.getLabel()).toBe('Overview');
|
|
3002
|
+
* ```
|
|
3003
|
+
*/
|
|
3004
|
+
async getSelectedTab() {
|
|
3005
|
+
const tabs = await this.getTabs();
|
|
3006
|
+
for (const tab of tabs) {
|
|
3007
|
+
if (await tab.isSelected()) {
|
|
3008
|
+
return tab;
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
throw new Error('No selected tab found');
|
|
3012
|
+
}
|
|
3013
|
+
/**
|
|
3014
|
+
* Selects a tab by filter criteria. Clicks the matching tab button.
|
|
3015
|
+
*
|
|
3016
|
+
* @param filter Filter to identify which tab to select.
|
|
3017
|
+
* @returns Promise that resolves when the tab has been selected.
|
|
3018
|
+
*
|
|
3019
|
+
* @example
|
|
3020
|
+
* ```typescript
|
|
3021
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
3022
|
+
*
|
|
3023
|
+
* // Select by label
|
|
3024
|
+
* await tabs.selectTab({ label: 'Settings' });
|
|
3025
|
+
*
|
|
3026
|
+
* // Select by regex
|
|
3027
|
+
* await tabs.selectTab({ label: /detail/i });
|
|
3028
|
+
* ```
|
|
3029
|
+
*/
|
|
3030
|
+
async selectTab(filter) {
|
|
3031
|
+
const tab = await this.getTab(filter);
|
|
3032
|
+
await tab.select();
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Gets the orientation of the tab group.
|
|
3036
|
+
*
|
|
3037
|
+
* @returns Promise resolving to 'horizontal' or 'vertical'.
|
|
3038
|
+
*
|
|
3039
|
+
* @example
|
|
3040
|
+
* ```typescript
|
|
3041
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
3042
|
+
* expect(await tabs.getOrientation()).toBe('horizontal');
|
|
3043
|
+
* ```
|
|
3044
|
+
*/
|
|
3045
|
+
async getOrientation() {
|
|
3046
|
+
const tablist = await this.locatorFor('[role="tablist"]')();
|
|
3047
|
+
return (await tablist.getAttribute('aria-orientation')) ?? 'horizontal';
|
|
3048
|
+
}
|
|
3049
|
+
/**
|
|
3050
|
+
* Gets the number of tabs.
|
|
3051
|
+
*
|
|
3052
|
+
* @returns Promise resolving to the tab count.
|
|
3053
|
+
*
|
|
3054
|
+
* @example
|
|
3055
|
+
* ```typescript
|
|
3056
|
+
* const tabs = await loader.getHarness(TnTabsHarness);
|
|
3057
|
+
* expect(await tabs.getTabCount()).toBe(3);
|
|
3058
|
+
* ```
|
|
3059
|
+
*/
|
|
3060
|
+
async getTabCount() {
|
|
3061
|
+
const tabs = await this.getTabs();
|
|
3062
|
+
return tabs.length;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
|
|
2669
3066
|
class TnKeyboardShortcutComponent {
|
|
2670
3067
|
shortcut = input('', ...(ngDevMode ? [{ debugName: "shortcut" }] : []));
|
|
2671
3068
|
platform = input('auto', ...(ngDevMode ? [{ debugName: "platform" }] : []));
|
|
@@ -7315,6 +7712,7 @@ class TnDialog {
|
|
|
7315
7712
|
return Promise.resolve().then(function () { return confirmDialog_component; }).then(m => {
|
|
7316
7713
|
const dialogRef = this.open(m.TnConfirmDialogComponent, {
|
|
7317
7714
|
data: opts,
|
|
7715
|
+
width: '488px',
|
|
7318
7716
|
role: 'alertdialog',
|
|
7319
7717
|
disableClose: true,
|
|
7320
7718
|
panelClass: [opts.destructive ? 'tn-dialog--destructive' : ''].filter(Boolean),
|
|
@@ -7408,14 +7806,14 @@ class TnConfirmDialogComponent {
|
|
|
7408
7806
|
ref = inject((DialogRef));
|
|
7409
7807
|
data = inject(DIALOG_DATA);
|
|
7410
7808
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7411
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: TnConfirmDialogComponent, isStandalone: true, selector: "tn-confirm-dialog", host: { properties: { "class.tn-dialog--destructive": "data.destructive" }, classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"
|
|
7809
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: TnConfirmDialogComponent, isStandalone: true, selector: "tn-confirm-dialog", host: { properties: { "class.tn-dialog--destructive": "data.destructive" }, classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"margin: 0;\">{{ data.message }}</p>\n <div tnDialogAction>\n <tn-button\n type=\"button\"\n variant=\"outline\"\n [label]=\"data.cancelText || 'Cancel'\"\n (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n", dependencies: [{ kind: "component", type: TnDialogShellComponent, selector: "tn-dialog-shell", inputs: ["title", "showFullscreenButton"] }, { kind: "component", type: TnButtonComponent, selector: "tn-button", inputs: ["primary", "color", "variant", "backgroundColor", "label", "disabled"], outputs: ["onClick"] }] });
|
|
7412
7810
|
}
|
|
7413
7811
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, decorators: [{
|
|
7414
7812
|
type: Component,
|
|
7415
7813
|
args: [{ selector: 'tn-confirm-dialog', standalone: true, imports: [TnDialogShellComponent, TnButtonComponent], host: {
|
|
7416
7814
|
'class': 'tn-dialog-shell',
|
|
7417
7815
|
'[class.tn-dialog--destructive]': 'data.destructive'
|
|
7418
|
-
}, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"
|
|
7816
|
+
}, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"margin: 0;\">{{ data.message }}</p>\n <div tnDialogAction>\n <tn-button\n type=\"button\"\n variant=\"outline\"\n [label]=\"data.cancelText || 'Cancel'\"\n (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n" }]
|
|
7419
7817
|
}] });
|
|
7420
7818
|
|
|
7421
7819
|
var confirmDialog_component = /*#__PURE__*/Object.freeze({
|
|
@@ -8912,5 +9310,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
8912
9310
|
* Generated bundle index. Do not edit.
|
|
8913
9311
|
*/
|
|
8914
9312
|
|
|
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 };
|
|
9313
|
+
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, 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 };
|
|
8916
9314
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|