@praxisui/tabs
Version:
Configurable tabs (group and nav) for Praxis UI with metadata-driven content and runtime editor.
274 lines (269 loc) • 10.5 kB
TypeScript
import * as i0 from '@angular/core';
import { OnInit, OnChanges, EventEmitter, SimpleChanges, Provider } from '@angular/core';
import { MatTabChangeEvent } from '@angular/material/tabs';
import { FormGroup } from '@angular/forms';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { WidgetDefinition, ComponentDocMeta, ComponentMetadataRegistry } from '@praxisui/core';
import { BehaviorSubject } from 'rxjs';
import { SettingsValueProvider } from '@praxisui/settings-panel';
interface TabsMetadata {
meta?: any;
appearance?: TabsAppearanceConfig;
behavior?: TabsBehaviorConfig;
events?: TabsEventConfig;
accessibility?: TabsAccessibilityConfig;
group?: TabGroupMetadata;
tabs?: TabMetadata[];
nav?: TabNavMetadata;
}
interface TabsAppearanceConfig {
density?: 'compact' | 'comfortable' | 'spacious';
themeClass?: string;
customCss?: string;
/** Optional runtime tokens mapped to CSS for per-instance styling */
tokens?: Partial<TabsStyleTokens>;
}
interface TabsBehaviorConfig {
lazyLoad?: boolean;
closeable?: boolean;
reorderable?: boolean;
}
interface TabsEventConfig {
}
interface TabsAccessibilityConfig {
ariaLabels?: {
[key: string]: string;
};
keyboardNavigation?: boolean;
highContrast?: boolean;
reduceMotion?: boolean;
}
interface TabGroupMetadata {
alignTabs?: 'start' | 'center' | 'end';
animationDuration?: string;
ariaLabel?: string;
ariaLabelledby?: string;
color?: 'primary' | 'accent' | 'warn';
contentTabIndex?: number;
disablePagination?: boolean;
disableRipple?: boolean;
dynamicHeight?: boolean;
fitInkBarToContent?: boolean;
headerPosition?: 'above' | 'below';
preserveContent?: boolean;
selectedIndex?: number;
stretchTabs?: boolean;
backgroundColor?: 'primary' | 'accent' | 'warn' | undefined;
}
interface TabMetadata {
id?: string;
ariaLabel?: string;
ariaLabelledby?: string;
textLabel?: string;
labelClass?: string | string[];
bodyClass?: string | string[];
disabled?: boolean;
content?: any[];
widgets?: WidgetDefinition[];
isActive?: boolean;
origin?: number;
position?: number;
}
interface TabNavMetadata {
animationDuration?: string;
color?: 'primary' | 'accent' | 'warn';
backgroundColor?: 'primary' | 'accent' | 'warn' | undefined;
disablePagination?: boolean;
disableRipple?: boolean;
fitInkBarToContent?: boolean;
selectedIndex?: number;
stretchTabs?: boolean;
links: TabLinkMetadata[];
}
interface TabLinkMetadata {
id?: string;
label: string;
active?: boolean;
disabled?: boolean;
disableRipple?: boolean;
fitInkBarToContent?: boolean;
content?: any[];
widgets?: WidgetDefinition[];
}
interface TabsStyleTokens {
'active-indicator-color': string;
'active-focus-indicator-color': string;
'active-hover-indicator-color': string;
'active-label-text-color': string;
'active-focus-label-text-color': string;
'active-hover-label-text-color': string;
'inactive-label-text-color': string;
'inactive-hover-label-text-color': string;
'inactive-focus-label-text-color': string;
'inactive-ripple-color': string;
'pagination-icon-color': string;
'divider-color': string;
'background-color': string;
}
declare class PraxisTabs implements OnInit, OnChanges {
private readonly settings;
private readonly storage;
private readonly snack;
config: TabsMetadata | null;
tabsId?: string;
editModeEnabled: boolean;
form: FormGroup | null;
context: Record<string, any> | null;
animationDone: EventEmitter<void>;
focusChange: EventEmitter<MatTabChangeEvent>;
selectedIndexChange: EventEmitter<number>;
selectedTabChange: EventEmitter<MatTabChangeEvent>;
indexFocused: EventEmitter<number>;
selectFocusedIndex: EventEmitter<number>;
widgetEvent: EventEmitter<{
tabId?: string;
tabIndex?: number;
linkId?: string;
linkIndex?: number;
sourceId: string;
output?: string;
payload?: any;
}>;
protected currentNavIndex: i0.WritableSignal<number>;
protected selectedIndexSignal: i0.WritableSignal<number>;
private groupLoaded;
private navLoaded;
ngOnInit(): void;
ngOnChanges(changes: SimpleChanges): void;
isNavMode(): boolean;
effectiveAnimationDuration(): string;
getNavActive(i: number): boolean;
onNavClick(i: number): void;
onNavDrop(event: CdkDragDrop<any>): void;
onSelectedIndexChange(index: number): void;
closeTab(index: number): void;
moveTab(index: number, delta: number): void;
openEditor(): void;
addEmptyTab(): void;
/** Clears persisted tabs configuration to fallback to defaults */
resetPreferences(): void;
openQuickSetup(): void;
private storageKey;
private isLazy;
protected groupContentReady(index: number): boolean;
protected navContentReady(index: number): boolean;
protected isEmptyGlobal(): boolean;
protected emitWidgetEvent(loc: {
tabId?: string;
tabIndex?: number;
linkId?: string;
linkIndex?: number;
}, ev: {
sourceId: string;
output?: string;
payload?: any;
}): void;
protected styleCss(): string | null;
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisTabs, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTabs, "praxis-tabs", never, { "config": { "alias": "config"; "required": false; }; "tabsId": { "alias": "tabsId"; "required": false; }; "editModeEnabled": { "alias": "editModeEnabled"; "required": false; }; "form": { "alias": "form"; "required": false; }; "context": { "alias": "context"; "required": false; }; }, { "animationDone": "animationDone"; "focusChange": "focusChange"; "selectedIndexChange": "selectedIndexChange"; "selectedTabChange": "selectedTabChange"; "indexFocused": "indexFocused"; "selectFocusedIndex": "selectFocusedIndex"; "widgetEvent": "widgetEvent"; }, never, never, true, never>;
}
declare const PRAXIS_TABS_COMPONENT_METADATA: ComponentDocMeta;
declare function providePraxisTabsMetadata(): Provider;
declare class PraxisTabsConfigEditor implements SettingsValueProvider {
private registry;
editedConfig: TabsMetadata;
private initialConfig;
jsonText: string;
isValid: boolean;
errorMsg: string;
componentOptions: Array<{
id: string;
friendlyName?: string;
}>;
selectedTabWidgetId: Record<number, string>;
selectedLinkWidgetId: Record<number, string>;
quickResourcePathTab: Record<number, string>;
quickResourcePathLink: Record<number, string>;
tokenList: readonly [{
readonly key: "active-indicator-color";
readonly label: "Indicador ativo";
}, {
readonly key: "active-label-text-color";
readonly label: "Texto ativo";
}, {
readonly key: "active-hover-indicator-color";
readonly label: "Indicador ativo (hover)";
}, {
readonly key: "active-hover-label-text-color";
readonly label: "Texto ativo (hover)";
}, {
readonly key: "active-focus-indicator-color";
readonly label: "Indicador ativo (focus)";
}, {
readonly key: "active-focus-label-text-color";
readonly label: "Texto ativo (focus)";
}, {
readonly key: "inactive-label-text-color";
readonly label: "Texto inativo";
}, {
readonly key: "inactive-hover-label-text-color";
readonly label: "Texto inativo (hover)";
}, {
readonly key: "inactive-focus-label-text-color";
readonly label: "Texto inativo (focus)";
}, {
readonly key: "pagination-icon-color";
readonly label: "Ícones de paginação";
}, {
readonly key: "divider-color";
readonly label: "Divisor/linha";
}, {
readonly key: "background-color";
readonly label: "Fundo do header";
}];
private presets;
isDirty$: BehaviorSubject<boolean>;
isValid$: BehaviorSubject<boolean>;
isBusy$: BehaviorSubject<boolean>;
constructor(data: any, registry: ComponentMetadataRegistry);
private updateDirty;
onJsonTextChange(text: string): void;
formatJson(): void;
getSettingsValue(): any;
onSave(): any;
reset(): void;
get appearance(): NonNullable<TabsMetadata['appearance']>;
onAppearanceChange(): void;
onTokenChange(key: string, value: string): void;
clearTokens(): void;
applyPreset(id: 'primary' | 'neutral' | 'high-contrast'): void;
scssSnippet(): string;
get group(): any;
get nav(): any;
get behavior(): any;
get accessibility(): any;
addTab(): void;
removeTab(index: number): void;
moveTab(index: number, delta: number): void;
addWidgetToTab(tabIndex: number): void;
removeWidgetFromTab(tabIndex: number, widgetIndex: number): void;
updateWidgetInputsTab(tabIndex: number, widgetIndex: number, text: string): void;
updateWidgetOutputsTab(tabIndex: number, widgetIndex: number, text: string): void;
addPresetToTab(tabIndex: number, type: 'form' | 'table' | 'crud'): void;
addLink(): void;
removeLink(index: number): void;
moveLink(index: number, delta: number): void;
addWidgetToLink(linkIndex: number): void;
removeWidgetFromLink(linkIndex: number, widgetIndex: number): void;
updateWidgetInputsLink(linkIndex: number, widgetIndex: number, text: string): void;
updateWidgetOutputsLink(linkIndex: number, widgetIndex: number, text: string): void;
addPresetToLink(linkIndex: number, type: 'form' | 'table' | 'crud'): void;
stringify(v: any): string;
getCompName(id: string): string;
onTabWidgetDrop(tabIndex: number, event: CdkDragDrop<WidgetDefinition[]>): void;
onLinkWidgetDrop(linkIndex: number, event: CdkDragDrop<WidgetDefinition[]>): void;
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisTabsConfigEditor, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTabsConfigEditor, "praxis-tabs-config-editor", never, {}, {}, never, never, true, never>;
}
export { PRAXIS_TABS_COMPONENT_METADATA, PraxisTabs, PraxisTabsConfigEditor, providePraxisTabsMetadata };
export type { TabGroupMetadata, TabLinkMetadata, TabMetadata, TabNavMetadata, TabsAccessibilityConfig, TabsAppearanceConfig, TabsBehaviorConfig, TabsEventConfig, TabsMetadata, TabsStyleTokens };