@m1z23r/ngx-ui 1.1.13 → 1.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/m1z23r-ngx-ui.mjs +489 -2
- package/fesm2022/m1z23r-ngx-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/m1z23r-ngx-ui.d.ts +180 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, Pipe, contentChildren, ViewChild, TemplateRef, contentChild, viewChild, DestroyRef } from '@angular/core';
|
|
3
|
-
import { isPlatformBrowser, NgTemplateOutlet, DOCUMENT, DecimalPipe } from '@angular/common';
|
|
3
|
+
import { isPlatformBrowser, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, DecimalPipe } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
6
|
|
|
@@ -535,6 +535,226 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
|
|
|
535
535
|
args: [{ providedIn: 'root' }]
|
|
536
536
|
}] });
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Reference to a dynamically created tab.
|
|
540
|
+
* Provides methods to close the tab and access its result.
|
|
541
|
+
*/
|
|
542
|
+
class TabRef {
|
|
543
|
+
closeFn;
|
|
544
|
+
activateFn;
|
|
545
|
+
resolvePromise;
|
|
546
|
+
resultPromise;
|
|
547
|
+
_isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : []));
|
|
548
|
+
/** Unique identifier for this tab */
|
|
549
|
+
id;
|
|
550
|
+
/** Whether this tab is currently active */
|
|
551
|
+
isActive = this._isActive.asReadonly();
|
|
552
|
+
constructor(id, closeFn, activateFn) {
|
|
553
|
+
this.closeFn = closeFn;
|
|
554
|
+
this.activateFn = activateFn;
|
|
555
|
+
this.id = id;
|
|
556
|
+
this.resultPromise = new Promise((resolve) => {
|
|
557
|
+
this.resolvePromise = resolve;
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Closes the tab with an optional result value.
|
|
562
|
+
*/
|
|
563
|
+
close(result) {
|
|
564
|
+
this.resolvePromise(result);
|
|
565
|
+
this.closeFn(this);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Activates this tab.
|
|
569
|
+
*/
|
|
570
|
+
activate() {
|
|
571
|
+
this.activateFn(this);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Returns a promise that resolves when the tab is closed.
|
|
575
|
+
* The promise resolves with the result passed to close(), or undefined if closed without a result.
|
|
576
|
+
*/
|
|
577
|
+
afterClosed() {
|
|
578
|
+
return this.resultPromise;
|
|
579
|
+
}
|
|
580
|
+
/** @internal */
|
|
581
|
+
_setActive(active) {
|
|
582
|
+
this._isActive.set(active);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Injection token for tab data passed to the component.
|
|
588
|
+
*/
|
|
589
|
+
const TAB_DATA = new InjectionToken('TAB_DATA');
|
|
590
|
+
/**
|
|
591
|
+
* Injection token for the tab reference.
|
|
592
|
+
*/
|
|
593
|
+
const TAB_REF = new InjectionToken('TAB_REF');
|
|
594
|
+
/**
|
|
595
|
+
* Default configuration for dynamic tabs.
|
|
596
|
+
*/
|
|
597
|
+
const DEFAULT_TAB_CONFIG = {
|
|
598
|
+
closable: true,
|
|
599
|
+
activate: true,
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Service for managing dynamic tabs.
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```typescript
|
|
607
|
+
* @Component({ ... })
|
|
608
|
+
* export class MyTabContent {
|
|
609
|
+
* private tabRef = inject(TAB_REF) as TabRef<string>;
|
|
610
|
+
* private data = inject(TAB_DATA) as { message: string };
|
|
611
|
+
*
|
|
612
|
+
* save() {
|
|
613
|
+
* this.tabRef.close('saved');
|
|
614
|
+
* }
|
|
615
|
+
* }
|
|
616
|
+
*
|
|
617
|
+
* // In parent component:
|
|
618
|
+
* const tabRef = this.tabsService.open(MyTabContent, {
|
|
619
|
+
* label: 'New Tab',
|
|
620
|
+
* data: { message: 'Hello' },
|
|
621
|
+
* closable: true
|
|
622
|
+
* });
|
|
623
|
+
*
|
|
624
|
+
* const result = await tabRef.afterClosed();
|
|
625
|
+
* ```
|
|
626
|
+
*/
|
|
627
|
+
class TabsService {
|
|
628
|
+
_tabs = signal([], ...(ngDevMode ? [{ debugName: "_tabs" }] : []));
|
|
629
|
+
_activeTabId = signal(null, ...(ngDevMode ? [{ debugName: "_activeTabId" }] : []));
|
|
630
|
+
idCounter = 0;
|
|
631
|
+
/** All currently open tabs */
|
|
632
|
+
tabs = this._tabs.asReadonly();
|
|
633
|
+
/** ID of the currently active tab */
|
|
634
|
+
activeTabId = this._activeTabId.asReadonly();
|
|
635
|
+
/** The currently active tab */
|
|
636
|
+
activeTab = computed(() => {
|
|
637
|
+
const activeId = this._activeTabId();
|
|
638
|
+
return this._tabs().find((t) => t.id === activeId) ?? null;
|
|
639
|
+
}, ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
640
|
+
/**
|
|
641
|
+
* Opens a new tab with the specified component.
|
|
642
|
+
*
|
|
643
|
+
* @param component - The component to render inside the tab
|
|
644
|
+
* @param config - Configuration options for the tab
|
|
645
|
+
* @returns A TabRef that can be used to close the tab and get results
|
|
646
|
+
*/
|
|
647
|
+
open(component, config) {
|
|
648
|
+
const mergedConfig = { ...DEFAULT_TAB_CONFIG, ...config };
|
|
649
|
+
const id = config.id ?? `tab-${++this.idCounter}`;
|
|
650
|
+
const tabRef = new TabRef(id, (ref) => this.close(ref), (ref) => this.activate(ref));
|
|
651
|
+
const tab = {
|
|
652
|
+
id,
|
|
653
|
+
label: config.label,
|
|
654
|
+
icon: config.icon,
|
|
655
|
+
component,
|
|
656
|
+
data: config.data,
|
|
657
|
+
closable: mergedConfig.closable,
|
|
658
|
+
tabRef: tabRef,
|
|
659
|
+
};
|
|
660
|
+
this._tabs.update((tabs) => [...tabs, tab]);
|
|
661
|
+
if (mergedConfig.activate) {
|
|
662
|
+
this.activateById(id);
|
|
663
|
+
}
|
|
664
|
+
return tabRef;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Closes a tab by its TabRef.
|
|
668
|
+
*/
|
|
669
|
+
close(tabRef) {
|
|
670
|
+
this.closeById(tabRef.id);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Closes a tab by its ID.
|
|
674
|
+
*/
|
|
675
|
+
closeById(id) {
|
|
676
|
+
const tabs = this._tabs();
|
|
677
|
+
const index = tabs.findIndex((t) => t.id === id);
|
|
678
|
+
if (index === -1)
|
|
679
|
+
return;
|
|
680
|
+
// If closing the active tab, activate another one
|
|
681
|
+
if (this._activeTabId() === id) {
|
|
682
|
+
const newActiveTab = tabs[index + 1] ?? tabs[index - 1];
|
|
683
|
+
this._activeTabId.set(newActiveTab?.id ?? null);
|
|
684
|
+
if (newActiveTab) {
|
|
685
|
+
newActiveTab.tabRef._setActive(true);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
// Update the closed tab's active state
|
|
689
|
+
tabs[index].tabRef._setActive(false);
|
|
690
|
+
this._tabs.update((t) => t.filter((tab) => tab.id !== id));
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Closes all tabs.
|
|
694
|
+
*/
|
|
695
|
+
closeAll() {
|
|
696
|
+
this._tabs().forEach((tab) => {
|
|
697
|
+
tab.tabRef._setActive(false);
|
|
698
|
+
});
|
|
699
|
+
this._tabs.set([]);
|
|
700
|
+
this._activeTabId.set(null);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Activates a tab by its TabRef.
|
|
704
|
+
*/
|
|
705
|
+
activate(tabRef) {
|
|
706
|
+
this.activateById(tabRef.id);
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Activates a tab by its ID.
|
|
710
|
+
*/
|
|
711
|
+
activateById(id) {
|
|
712
|
+
const tabs = this._tabs();
|
|
713
|
+
const tab = tabs.find((t) => t.id === id);
|
|
714
|
+
if (!tab)
|
|
715
|
+
return;
|
|
716
|
+
// Deactivate current tab
|
|
717
|
+
const currentActive = tabs.find((t) => t.id === this._activeTabId());
|
|
718
|
+
if (currentActive) {
|
|
719
|
+
currentActive.tabRef._setActive(false);
|
|
720
|
+
}
|
|
721
|
+
// Activate new tab
|
|
722
|
+
tab.tabRef._setActive(true);
|
|
723
|
+
this._activeTabId.set(id);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Creates an injector with TAB_DATA and TAB_REF for a tab component.
|
|
727
|
+
* @internal
|
|
728
|
+
*/
|
|
729
|
+
_createInjector(parentInjector, data, tabRef) {
|
|
730
|
+
return Injector.create({
|
|
731
|
+
providers: [
|
|
732
|
+
{ provide: TAB_DATA, useValue: data },
|
|
733
|
+
{ provide: TAB_REF, useValue: tabRef },
|
|
734
|
+
],
|
|
735
|
+
parent: parentInjector,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Gets a tab by its ID.
|
|
740
|
+
*/
|
|
741
|
+
getTab(id) {
|
|
742
|
+
return this._tabs().find((t) => t.id === id);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Updates a tab's label.
|
|
746
|
+
*/
|
|
747
|
+
updateLabel(id, label) {
|
|
748
|
+
this._tabs.update((tabs) => tabs.map((tab) => (tab.id === id ? { ...tab, label } : tab)));
|
|
749
|
+
}
|
|
750
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TabsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
751
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TabsService, providedIn: 'root' });
|
|
752
|
+
}
|
|
753
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TabsService, decorators: [{
|
|
754
|
+
type: Injectable,
|
|
755
|
+
args: [{ providedIn: 'root' }]
|
|
756
|
+
}] });
|
|
757
|
+
|
|
538
758
|
/**
|
|
539
759
|
* Modal wrapper component with backdrop, header, body, and footer slots.
|
|
540
760
|
* Uses content projection for flexible content.
|
|
@@ -2500,6 +2720,273 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
|
|
|
2500
2720
|
args: [{ selector: 'ui-tabs', standalone: true, imports: [NgTemplateOutlet, TabActivePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-tabs\" [class]=\"tabsClasses()\">\n <div\n #tabList\n class=\"ui-tabs__list\"\n role=\"tablist\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n @for (tab of tabs(); track tab.id() || $index; let i = $index) {\n @let active = tab | tabActive:i:activeTab();\n <button\n #tabButton\n type=\"button\"\n class=\"ui-tabs__tab\"\n role=\"tab\"\n [class.ui-tabs__tab--active]=\"active\"\n [class.ui-tabs__tab--disabled]=\"tab.disabled()\"\n [attr.aria-selected]=\"active\"\n [attr.aria-controls]=\"'panel-' + (tab.id() || i)\"\n [attr.tabindex]=\"active ? 0 : -1\"\n [disabled]=\"tab.disabled()\"\n (click)=\"selectTab(tab, i)\"\n (keydown)=\"handleKeyDown($event, i)\"\n >\n @if (tab.iconTemplate()) {\n <span class=\"ui-tabs__tab-icon\">\n <ng-container *ngTemplateOutlet=\"tab.iconTemplate()!\" />\n </span>\n }\n {{ tab.label() }}\n </button>\n }\n @if (variant() === 'underline') {\n <span\n class=\"ui-tabs__indicator\"\n [style.left.px]=\"indicatorLeft()\"\n [style.width.px]=\"indicatorWidth()\"\n ></span>\n }\n </div>\n <div class=\"ui-tabs__panels\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block}.ui-tabs__list{display:flex;position:relative;gap:var(--ui-spacing-xs)}.ui-tabs__tab{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.5rem 1rem;border:none;background:transparent;color:var(--ui-text-muted);font-weight:500;cursor:pointer;transition:all var(--ui-transition-fast);white-space:nowrap}.ui-tabs__tab:hover:not(:disabled){color:var(--ui-text)}.ui-tabs__tab:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px;border-radius:var(--ui-radius-sm)}.ui-tabs__tab--active{color:var(--ui-primary)}.ui-tabs__tab--disabled{opacity:.5;cursor:not-allowed}.ui-tabs__tab-icon{display:flex;align-items:center;justify-content:center}.ui-tabs__panels{margin-top:var(--ui-spacing-md)}.ui-tabs--default .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--default .ui-tabs__tab{margin-bottom:-1px;border-bottom:2px solid transparent;border-radius:var(--ui-radius-sm) var(--ui-radius-sm) 0 0}.ui-tabs--default .ui-tabs__tab--active{border-bottom-color:var(--ui-primary)}.ui-tabs--pills .ui-tabs__list{background-color:var(--ui-bg-tertiary);padding:3px;border-radius:var(--ui-radius-md);gap:2px}.ui-tabs--pills .ui-tabs__tab{border-radius:var(--ui-radius-sm)}.ui-tabs--pills .ui-tabs__tab--active{background-color:var(--ui-bg);color:var(--ui-text);box-shadow:var(--ui-shadow-sm)}.ui-tabs--underline .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--underline .ui-tabs__tab{padding-bottom:.75rem}.ui-tabs--underline .ui-tabs__indicator{position:absolute;bottom:0;height:2px;background-color:var(--ui-primary);transition:left var(--ui-transition-normal),width var(--ui-transition-normal)}.ui-tabs--sm .ui-tabs__tab{padding:.375rem .75rem;font-size:var(--ui-font-sm)}.ui-tabs--md .ui-tabs__tab{padding:.5rem 1rem;font-size:var(--ui-font-sm)}.ui-tabs--lg .ui-tabs__tab{padding:.625rem 1.25rem;font-size:var(--ui-font-md)}.ui-tabs--sm.ui-tabs--underline .ui-tabs__tab{padding-bottom:.5rem}.ui-tabs--lg.ui-tabs--underline .ui-tabs__tab{padding-bottom:.875rem}\n"] }]
|
|
2501
2721
|
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TabComponent), { isSignal: true }] }], tabList: [{ type: i0.ViewChild, args: ['tabList', { isSignal: true }] }] } });
|
|
2502
2722
|
|
|
2723
|
+
class DynamicTabsComponent {
|
|
2724
|
+
tabsService = inject(TabsService);
|
|
2725
|
+
injector = inject(Injector);
|
|
2726
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
2727
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2728
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
2729
|
+
tabList = viewChild('tabList', ...(ngDevMode ? [{ debugName: "tabList" }] : []));
|
|
2730
|
+
indicatorLeft = signal(0, ...(ngDevMode ? [{ debugName: "indicatorLeft" }] : []));
|
|
2731
|
+
indicatorWidth = signal(0, ...(ngDevMode ? [{ debugName: "indicatorWidth" }] : []));
|
|
2732
|
+
tabs = this.tabsService.tabs;
|
|
2733
|
+
activeTabId = this.tabsService.activeTabId;
|
|
2734
|
+
injectorCache = new Map();
|
|
2735
|
+
tabsClasses = computed(() => {
|
|
2736
|
+
return `ui-tabs--${this.variant()} ui-tabs--${this.size()}`;
|
|
2737
|
+
}, ...(ngDevMode ? [{ debugName: "tabsClasses" }] : []));
|
|
2738
|
+
constructor() {
|
|
2739
|
+
effect(() => {
|
|
2740
|
+
const _ = this.activeTabId();
|
|
2741
|
+
this.updateIndicator();
|
|
2742
|
+
});
|
|
2743
|
+
// Clean up injector cache when tabs are removed
|
|
2744
|
+
effect(() => {
|
|
2745
|
+
const currentTabs = this.tabs();
|
|
2746
|
+
const currentIds = new Set(currentTabs.map((t) => t.id));
|
|
2747
|
+
for (const id of this.injectorCache.keys()) {
|
|
2748
|
+
if (!currentIds.has(id)) {
|
|
2749
|
+
this.injectorCache.delete(id);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
});
|
|
2753
|
+
}
|
|
2754
|
+
getInjector(tab) {
|
|
2755
|
+
let injector = this.injectorCache.get(tab.id);
|
|
2756
|
+
if (!injector) {
|
|
2757
|
+
injector = this.tabsService._createInjector(this.injector, tab.data, tab.tabRef);
|
|
2758
|
+
this.injectorCache.set(tab.id, injector);
|
|
2759
|
+
}
|
|
2760
|
+
return injector;
|
|
2761
|
+
}
|
|
2762
|
+
selectTab(tab) {
|
|
2763
|
+
this.tabsService.activateById(tab.id);
|
|
2764
|
+
}
|
|
2765
|
+
closeTab(event, tab) {
|
|
2766
|
+
event.stopPropagation();
|
|
2767
|
+
tab.tabRef.close();
|
|
2768
|
+
}
|
|
2769
|
+
handleKeyDown(event, currentTab) {
|
|
2770
|
+
const tabList = this.tabs();
|
|
2771
|
+
if (tabList.length === 0)
|
|
2772
|
+
return;
|
|
2773
|
+
const currentIndex = tabList.findIndex((t) => t.id === currentTab.id);
|
|
2774
|
+
let nextIndex = -1;
|
|
2775
|
+
switch (event.key) {
|
|
2776
|
+
case 'ArrowLeft':
|
|
2777
|
+
event.preventDefault();
|
|
2778
|
+
nextIndex = (currentIndex - 1 + tabList.length) % tabList.length;
|
|
2779
|
+
break;
|
|
2780
|
+
case 'ArrowRight':
|
|
2781
|
+
event.preventDefault();
|
|
2782
|
+
nextIndex = (currentIndex + 1) % tabList.length;
|
|
2783
|
+
break;
|
|
2784
|
+
case 'Home':
|
|
2785
|
+
event.preventDefault();
|
|
2786
|
+
nextIndex = 0;
|
|
2787
|
+
break;
|
|
2788
|
+
case 'End':
|
|
2789
|
+
event.preventDefault();
|
|
2790
|
+
nextIndex = tabList.length - 1;
|
|
2791
|
+
break;
|
|
2792
|
+
case 'Delete':
|
|
2793
|
+
if (currentTab.closable) {
|
|
2794
|
+
event.preventDefault();
|
|
2795
|
+
currentTab.tabRef.close();
|
|
2796
|
+
}
|
|
2797
|
+
return;
|
|
2798
|
+
default:
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
if (nextIndex >= 0) {
|
|
2802
|
+
const nextTab = tabList[nextIndex];
|
|
2803
|
+
this.tabsService.activateById(nextTab.id);
|
|
2804
|
+
this.focusTab(nextIndex);
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
focusTab(index) {
|
|
2808
|
+
const tabListEl = this.tabList()?.nativeElement;
|
|
2809
|
+
if (!tabListEl)
|
|
2810
|
+
return;
|
|
2811
|
+
const buttons = tabListEl.querySelectorAll('.ui-tabs__tab');
|
|
2812
|
+
buttons[index]?.focus();
|
|
2813
|
+
}
|
|
2814
|
+
updateIndicator() {
|
|
2815
|
+
if (this.variant() !== 'underline')
|
|
2816
|
+
return;
|
|
2817
|
+
const tabListEl = this.tabList()?.nativeElement;
|
|
2818
|
+
if (!tabListEl)
|
|
2819
|
+
return;
|
|
2820
|
+
const buttons = tabListEl.querySelectorAll('.ui-tabs__tab');
|
|
2821
|
+
const activeId = this.activeTabId();
|
|
2822
|
+
const tabs = this.tabs();
|
|
2823
|
+
const activeIndex = tabs.findIndex((t) => t.id === activeId);
|
|
2824
|
+
if (activeIndex >= 0 && activeIndex < buttons.length) {
|
|
2825
|
+
const activeButton = buttons[activeIndex];
|
|
2826
|
+
this.indicatorLeft.set(activeButton.offsetLeft);
|
|
2827
|
+
this.indicatorWidth.set(activeButton.offsetWidth);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DynamicTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2831
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: DynamicTabsComponent, isStandalone: true, selector: "ui-dynamic-tabs", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "tabList", first: true, predicate: ["tabList"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
2832
|
+
<div class="ui-tabs" [class]="tabsClasses()">
|
|
2833
|
+
<div
|
|
2834
|
+
#tabList
|
|
2835
|
+
class="ui-tabs__list"
|
|
2836
|
+
role="tablist"
|
|
2837
|
+
[attr.aria-label]="ariaLabel()"
|
|
2838
|
+
>
|
|
2839
|
+
@for (tab of tabs(); track tab.id) {
|
|
2840
|
+
@let active = tab.id === activeTabId();
|
|
2841
|
+
<button
|
|
2842
|
+
type="button"
|
|
2843
|
+
class="ui-tabs__tab"
|
|
2844
|
+
role="tab"
|
|
2845
|
+
[class.ui-tabs__tab--active]="active"
|
|
2846
|
+
[class.ui-tabs__tab--closable]="tab.closable"
|
|
2847
|
+
[attr.aria-selected]="active"
|
|
2848
|
+
[attr.aria-controls]="'panel-' + tab.id"
|
|
2849
|
+
[attr.tabindex]="active ? 0 : -1"
|
|
2850
|
+
(click)="selectTab(tab)"
|
|
2851
|
+
(keydown)="handleKeyDown($event, tab)"
|
|
2852
|
+
>
|
|
2853
|
+
@if (tab.icon) {
|
|
2854
|
+
<span class="ui-tabs__tab-icon">
|
|
2855
|
+
<ng-container *ngTemplateOutlet="tab.icon" />
|
|
2856
|
+
</span>
|
|
2857
|
+
}
|
|
2858
|
+
<span class="ui-tabs__tab-label">{{ tab.label }}</span>
|
|
2859
|
+
@if (tab.closable) {
|
|
2860
|
+
<button
|
|
2861
|
+
type="button"
|
|
2862
|
+
class="ui-tabs__tab-close"
|
|
2863
|
+
aria-label="Close tab"
|
|
2864
|
+
(click)="closeTab($event, tab)"
|
|
2865
|
+
>
|
|
2866
|
+
<svg
|
|
2867
|
+
width="14"
|
|
2868
|
+
height="14"
|
|
2869
|
+
viewBox="0 0 24 24"
|
|
2870
|
+
fill="none"
|
|
2871
|
+
stroke="currentColor"
|
|
2872
|
+
stroke-width="2"
|
|
2873
|
+
stroke-linecap="round"
|
|
2874
|
+
stroke-linejoin="round"
|
|
2875
|
+
>
|
|
2876
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
2877
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
2878
|
+
</svg>
|
|
2879
|
+
</button>
|
|
2880
|
+
}
|
|
2881
|
+
</button>
|
|
2882
|
+
}
|
|
2883
|
+
@if (variant() === 'underline') {
|
|
2884
|
+
<span
|
|
2885
|
+
class="ui-tabs__indicator"
|
|
2886
|
+
[style.left.px]="indicatorLeft()"
|
|
2887
|
+
[style.width.px]="indicatorWidth()"
|
|
2888
|
+
></span>
|
|
2889
|
+
}
|
|
2890
|
+
</div>
|
|
2891
|
+
<div class="ui-tabs__panels">
|
|
2892
|
+
@for (tab of tabs(); track tab.id) {
|
|
2893
|
+
@if (tab.id === activeTabId()) {
|
|
2894
|
+
<div
|
|
2895
|
+
class="ui-tab-panel"
|
|
2896
|
+
role="tabpanel"
|
|
2897
|
+
[attr.id]="'panel-' + tab.id"
|
|
2898
|
+
>
|
|
2899
|
+
<ng-container
|
|
2900
|
+
*ngComponentOutlet="tab.component; injector: getInjector(tab)"
|
|
2901
|
+
/>
|
|
2902
|
+
</div>
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
</div>
|
|
2906
|
+
</div>
|
|
2907
|
+
`, isInline: true, styles: [":host{display:block}.ui-tabs__list{display:flex;position:relative;gap:var(--ui-spacing-xs)}.ui-tabs__tab{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.5rem 1rem;border:none;background:transparent;color:var(--ui-text-muted);font-weight:500;cursor:pointer;transition:all var(--ui-transition-fast);white-space:nowrap}.ui-tabs__tab:hover:not(:disabled){color:var(--ui-text)}.ui-tabs__tab:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px;border-radius:var(--ui-radius-sm)}.ui-tabs__tab--active{color:var(--ui-primary)}.ui-tabs__tab--disabled{opacity:.5;cursor:not-allowed}.ui-tabs__tab-icon{display:flex;align-items:center;justify-content:center}.ui-tabs__panels{margin-top:var(--ui-spacing-md)}.ui-tabs--default .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--default .ui-tabs__tab{margin-bottom:-1px;border-bottom:2px solid transparent;border-radius:var(--ui-radius-sm) var(--ui-radius-sm) 0 0}.ui-tabs--default .ui-tabs__tab--active{border-bottom-color:var(--ui-primary)}.ui-tabs--pills .ui-tabs__list{background-color:var(--ui-bg-tertiary);padding:3px;border-radius:var(--ui-radius-md);gap:2px}.ui-tabs--pills .ui-tabs__tab{border-radius:var(--ui-radius-sm)}.ui-tabs--pills .ui-tabs__tab--active{background-color:var(--ui-bg);color:var(--ui-text);box-shadow:var(--ui-shadow-sm)}.ui-tabs--underline .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--underline .ui-tabs__tab{padding-bottom:.75rem}.ui-tabs--underline .ui-tabs__indicator{position:absolute;bottom:0;height:2px;background-color:var(--ui-primary);transition:left var(--ui-transition-normal),width var(--ui-transition-normal)}.ui-tabs--sm .ui-tabs__tab{padding:.375rem .75rem;font-size:var(--ui-font-sm)}.ui-tabs--md .ui-tabs__tab{padding:.5rem 1rem;font-size:var(--ui-font-sm)}.ui-tabs--lg .ui-tabs__tab{padding:.625rem 1.25rem;font-size:var(--ui-font-md)}.ui-tabs--sm.ui-tabs--underline .ui-tabs__tab{padding-bottom:.5rem}.ui-tabs--lg.ui-tabs--underline .ui-tabs__tab{padding-bottom:.875rem}\n", ".ui-tabs__tab--closable{padding-right:var(--ui-spacing-xs)}.ui-tabs__tab-label{flex:1}.ui-tabs__tab-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-left:var(--ui-spacing-xs);padding:0;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;opacity:0;transition:all var(--ui-transition-fast)}.ui-tabs__tab:hover .ui-tabs__tab-close,.ui-tabs__tab:focus-within .ui-tabs__tab-close{opacity:1}.ui-tabs__tab-close:hover{background:var(--ui-bg-hover);color:var(--ui-danger)}.ui-tabs__tab-close:focus-visible{opacity:1;outline:2px solid var(--ui-primary);outline-offset:1px}.ui-tab-panel{animation:fadeIn var(--ui-transition-fast)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2908
|
+
}
|
|
2909
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DynamicTabsComponent, decorators: [{
|
|
2910
|
+
type: Component,
|
|
2911
|
+
args: [{ selector: 'ui-dynamic-tabs', standalone: true, imports: [NgComponentOutlet, NgTemplateOutlet], template: `
|
|
2912
|
+
<div class="ui-tabs" [class]="tabsClasses()">
|
|
2913
|
+
<div
|
|
2914
|
+
#tabList
|
|
2915
|
+
class="ui-tabs__list"
|
|
2916
|
+
role="tablist"
|
|
2917
|
+
[attr.aria-label]="ariaLabel()"
|
|
2918
|
+
>
|
|
2919
|
+
@for (tab of tabs(); track tab.id) {
|
|
2920
|
+
@let active = tab.id === activeTabId();
|
|
2921
|
+
<button
|
|
2922
|
+
type="button"
|
|
2923
|
+
class="ui-tabs__tab"
|
|
2924
|
+
role="tab"
|
|
2925
|
+
[class.ui-tabs__tab--active]="active"
|
|
2926
|
+
[class.ui-tabs__tab--closable]="tab.closable"
|
|
2927
|
+
[attr.aria-selected]="active"
|
|
2928
|
+
[attr.aria-controls]="'panel-' + tab.id"
|
|
2929
|
+
[attr.tabindex]="active ? 0 : -1"
|
|
2930
|
+
(click)="selectTab(tab)"
|
|
2931
|
+
(keydown)="handleKeyDown($event, tab)"
|
|
2932
|
+
>
|
|
2933
|
+
@if (tab.icon) {
|
|
2934
|
+
<span class="ui-tabs__tab-icon">
|
|
2935
|
+
<ng-container *ngTemplateOutlet="tab.icon" />
|
|
2936
|
+
</span>
|
|
2937
|
+
}
|
|
2938
|
+
<span class="ui-tabs__tab-label">{{ tab.label }}</span>
|
|
2939
|
+
@if (tab.closable) {
|
|
2940
|
+
<button
|
|
2941
|
+
type="button"
|
|
2942
|
+
class="ui-tabs__tab-close"
|
|
2943
|
+
aria-label="Close tab"
|
|
2944
|
+
(click)="closeTab($event, tab)"
|
|
2945
|
+
>
|
|
2946
|
+
<svg
|
|
2947
|
+
width="14"
|
|
2948
|
+
height="14"
|
|
2949
|
+
viewBox="0 0 24 24"
|
|
2950
|
+
fill="none"
|
|
2951
|
+
stroke="currentColor"
|
|
2952
|
+
stroke-width="2"
|
|
2953
|
+
stroke-linecap="round"
|
|
2954
|
+
stroke-linejoin="round"
|
|
2955
|
+
>
|
|
2956
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
2957
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
2958
|
+
</svg>
|
|
2959
|
+
</button>
|
|
2960
|
+
}
|
|
2961
|
+
</button>
|
|
2962
|
+
}
|
|
2963
|
+
@if (variant() === 'underline') {
|
|
2964
|
+
<span
|
|
2965
|
+
class="ui-tabs__indicator"
|
|
2966
|
+
[style.left.px]="indicatorLeft()"
|
|
2967
|
+
[style.width.px]="indicatorWidth()"
|
|
2968
|
+
></span>
|
|
2969
|
+
}
|
|
2970
|
+
</div>
|
|
2971
|
+
<div class="ui-tabs__panels">
|
|
2972
|
+
@for (tab of tabs(); track tab.id) {
|
|
2973
|
+
@if (tab.id === activeTabId()) {
|
|
2974
|
+
<div
|
|
2975
|
+
class="ui-tab-panel"
|
|
2976
|
+
role="tabpanel"
|
|
2977
|
+
[attr.id]="'panel-' + tab.id"
|
|
2978
|
+
>
|
|
2979
|
+
<ng-container
|
|
2980
|
+
*ngComponentOutlet="tab.component; injector: getInjector(tab)"
|
|
2981
|
+
/>
|
|
2982
|
+
</div>
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
</div>
|
|
2986
|
+
</div>
|
|
2987
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.ui-tabs__list{display:flex;position:relative;gap:var(--ui-spacing-xs)}.ui-tabs__tab{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.5rem 1rem;border:none;background:transparent;color:var(--ui-text-muted);font-weight:500;cursor:pointer;transition:all var(--ui-transition-fast);white-space:nowrap}.ui-tabs__tab:hover:not(:disabled){color:var(--ui-text)}.ui-tabs__tab:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px;border-radius:var(--ui-radius-sm)}.ui-tabs__tab--active{color:var(--ui-primary)}.ui-tabs__tab--disabled{opacity:.5;cursor:not-allowed}.ui-tabs__tab-icon{display:flex;align-items:center;justify-content:center}.ui-tabs__panels{margin-top:var(--ui-spacing-md)}.ui-tabs--default .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--default .ui-tabs__tab{margin-bottom:-1px;border-bottom:2px solid transparent;border-radius:var(--ui-radius-sm) var(--ui-radius-sm) 0 0}.ui-tabs--default .ui-tabs__tab--active{border-bottom-color:var(--ui-primary)}.ui-tabs--pills .ui-tabs__list{background-color:var(--ui-bg-tertiary);padding:3px;border-radius:var(--ui-radius-md);gap:2px}.ui-tabs--pills .ui-tabs__tab{border-radius:var(--ui-radius-sm)}.ui-tabs--pills .ui-tabs__tab--active{background-color:var(--ui-bg);color:var(--ui-text);box-shadow:var(--ui-shadow-sm)}.ui-tabs--underline .ui-tabs__list{border-bottom:1px solid var(--ui-border)}.ui-tabs--underline .ui-tabs__tab{padding-bottom:.75rem}.ui-tabs--underline .ui-tabs__indicator{position:absolute;bottom:0;height:2px;background-color:var(--ui-primary);transition:left var(--ui-transition-normal),width var(--ui-transition-normal)}.ui-tabs--sm .ui-tabs__tab{padding:.375rem .75rem;font-size:var(--ui-font-sm)}.ui-tabs--md .ui-tabs__tab{padding:.5rem 1rem;font-size:var(--ui-font-sm)}.ui-tabs--lg .ui-tabs__tab{padding:.625rem 1.25rem;font-size:var(--ui-font-md)}.ui-tabs--sm.ui-tabs--underline .ui-tabs__tab{padding-bottom:.5rem}.ui-tabs--lg.ui-tabs--underline .ui-tabs__tab{padding-bottom:.875rem}\n", ".ui-tabs__tab--closable{padding-right:var(--ui-spacing-xs)}.ui-tabs__tab-label{flex:1}.ui-tabs__tab-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-left:var(--ui-spacing-xs);padding:0;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;opacity:0;transition:all var(--ui-transition-fast)}.ui-tabs__tab:hover .ui-tabs__tab-close,.ui-tabs__tab:focus-within .ui-tabs__tab-close{opacity:1}.ui-tabs__tab-close:hover{background:var(--ui-bg-hover);color:var(--ui-danger)}.ui-tabs__tab-close:focus-visible{opacity:1;outline:2px solid var(--ui-primary);outline-offset:1px}.ui-tab-panel{animation:fadeIn var(--ui-transition-fast)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
2988
|
+
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], tabList: [{ type: i0.ViewChild, args: ['tabList', { isSignal: true }] }] } });
|
|
2989
|
+
|
|
2503
2990
|
class AccordionHeaderDirective {
|
|
2504
2991
|
templateRef = inject(TemplateRef);
|
|
2505
2992
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AccordionHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -5137,5 +5624,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
|
|
|
5137
5624
|
* Generated bundle index. Do not edit.
|
|
5138
5625
|
*/
|
|
5139
5626
|
|
|
5140
|
-
export { AccordionComponent, AccordionHeaderDirective, AccordionItemComponent, AlertComponent, BadgeComponent, ButtonComponent, CardComponent, CellTemplateDirective, CellValuePipe, CheckboxComponent, ChipInputComponent, ChipTemplateDirective, CircularProgressComponent, ContentComponent, ContextMenuDirective, DIALOG_DATA, DIALOG_REF, DatepickerComponent, DatetimepickerComponent, DialogRef, DialogService, DropdownComponent, DropdownDividerComponent, DropdownItemComponent, DropdownTriggerDirective, FileChooserComponent, FilePreviewPipe, FileSizePipe, FooterComponent, InputComponent, LOADABLE, LoadingDirective, LoadingService, ModalComponent, NavbarComponent, OptionComponent, OptionTemplateDirective, PaginationComponent, ProgressComponent, RadioComponent, RadioGroupComponent, SelectComponent, ShellComponent, SidebarComponent, SidebarService, SidebarToggleComponent, SliderComponent, SpinnerComponent, SplitComponent, SplitPaneComponent, SwitchComponent, TabActivePipe, TabComponent, TabIconDirective, TableComponent, TabsComponent, TextareaComponent, TimepickerComponent, ToastRef, ToastService, TooltipDirective, TreeComponent, TreeNodeComponent };
|
|
5627
|
+
export { AccordionComponent, AccordionHeaderDirective, AccordionItemComponent, AlertComponent, BadgeComponent, ButtonComponent, CardComponent, CellTemplateDirective, CellValuePipe, CheckboxComponent, ChipInputComponent, ChipTemplateDirective, CircularProgressComponent, ContentComponent, ContextMenuDirective, DIALOG_DATA, DIALOG_REF, DatepickerComponent, DatetimepickerComponent, DialogRef, DialogService, DropdownComponent, DropdownDividerComponent, DropdownItemComponent, DropdownTriggerDirective, DynamicTabsComponent, FileChooserComponent, FilePreviewPipe, FileSizePipe, FooterComponent, InputComponent, LOADABLE, LoadingDirective, LoadingService, ModalComponent, NavbarComponent, OptionComponent, OptionTemplateDirective, PaginationComponent, ProgressComponent, RadioComponent, RadioGroupComponent, SelectComponent, ShellComponent, SidebarComponent, SidebarService, SidebarToggleComponent, SliderComponent, SpinnerComponent, SplitComponent, SplitPaneComponent, SwitchComponent, TAB_DATA, TAB_REF, TabActivePipe, TabComponent, TabIconDirective, TabRef, TableComponent, TabsComponent, TabsService, TextareaComponent, TimepickerComponent, ToastRef, ToastService, TooltipDirective, TreeComponent, TreeNodeComponent };
|
|
5141
5628
|
//# sourceMappingURL=m1z23r-ngx-ui.mjs.map
|