@praxisui/tabs 8.0.0-beta.11 → 8.0.0-beta.12
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/README.md +36 -2
- package/fesm2022/praxisui-tabs.mjs +320 -105
- package/index.d.ts +29 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ Inputs
|
|
|
75
75
|
- `componentInstanceId?: string` Opcional para desambiguar múltiplas instâncias com o mesmo `tabsId` na mesma rota.
|
|
76
76
|
- `form?: FormGroup` FormGroup opcional para campos dinâmicos declarados em `content`.
|
|
77
77
|
- `context?: any` Contexto propagado a widgets internos (via `DynamicWidgetLoader`).
|
|
78
|
+
- `selectedIndex?: number` Índice ativo controlado por composição; não reemite `selectedIndexChange`.
|
|
78
79
|
- `enableCustomization?: boolean` Exibe botão de edição quando verdadeiro (abre o editor).
|
|
79
80
|
|
|
80
81
|
Outputs
|
|
@@ -83,6 +84,38 @@ Outputs
|
|
|
83
84
|
- `focusChange, animationDone, indexFocused, selectFocusedIndex` Eventos nativos do Angular Material.
|
|
84
85
|
- `widgetEvent: WidgetEventEnvelope` Bridge avançada/legado para transporte de eventos dos widgets internos com contexto da aba/link. Para conexões novas de widgets internos, use `composition.links` com `component-port + nestedPath`.
|
|
85
86
|
|
|
87
|
+
## Uso Controlado por Composição
|
|
88
|
+
|
|
89
|
+
`selectedIndex` é a porta pública para controlar a aba ativa a partir de estado externo ou de outro componente. Quando esse input é aplicado, o componente atualiza a aba ativa sem reemitir `selectedIndexChange`, evitando ciclos entre `state -> selectedIndex` e `selectedIndexChange -> state`.
|
|
90
|
+
|
|
91
|
+
Padrão recomendado para páginas dinâmicas:
|
|
92
|
+
|
|
93
|
+
- grave a seleção do usuário com `selectedIndexChange -> state`;
|
|
94
|
+
- projete o estado de volta com `state -> selectedIndex`;
|
|
95
|
+
- declare `selectedIndex` depois de `config` em `bindingOrder`, para que a configuração seja carregada antes da seleção controlada;
|
|
96
|
+
- não persista `inputs.selectedIndex` estático em recipes quando a seleção vem de `composition.links`.
|
|
97
|
+
|
|
98
|
+
Quando existe configuração persistida por `tabsId`, o valor controlado por `selectedIndex` vence a restauração local depois do carregamento da config. Essa projeção controlada não grava uma nova preferência no storage; somente interações diretas do usuário persistem seleção. Isso mantém o estado canônico da composição como fonte de verdade da navegação ativa sem transformar navegação transitória em configuração salva. Em modo `nav`, o índice controla `nav.links`; em modo `group`, controla `tabs`.
|
|
99
|
+
|
|
100
|
+
Exemplo canônico:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"links": [
|
|
105
|
+
{
|
|
106
|
+
"id": "tabs.selectedIndexChange->state.navigation.activeTabIndex",
|
|
107
|
+
"from": { "kind": "component-port", "ref": { "widget": "workspaceTabs", "port": "selectedIndexChange" } },
|
|
108
|
+
"to": { "kind": "state", "ref": { "path": "navigation.activeTabIndex", "layer": "values", "write": true } }
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "state.navigation.activeTabIndex->tabs.selectedIndex",
|
|
112
|
+
"from": { "kind": "state", "ref": { "path": "navigation.activeTabIndex", "layer": "values" } },
|
|
113
|
+
"to": { "kind": "component-port", "ref": { "widget": "workspaceTabs", "port": "selectedIndex" } }
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
86
119
|
Persistência
|
|
87
120
|
- Quando `tabsId` é fornecido, a configuração é salva/recuperada em `AsyncConfigStorage` na chave `tabs:<component_id>`.
|
|
88
121
|
- O `component_id` é derivado via `ComponentKeyService` (inclui rota, tipo de componente, `tabsId` e `componentInstanceId` quando informado).
|
|
@@ -110,8 +143,8 @@ export interface TabsMetadata {
|
|
|
110
143
|
behavior?: { lazyLoad?: boolean; closeable?: boolean; reorderable?: boolean };
|
|
111
144
|
accessibility?: { highContrast?: boolean; reduceMotion?: boolean };
|
|
112
145
|
group?: { alignTabs?: 'start' | 'center' | 'end'; headerPosition?: 'above'|'below'; selectedIndex?: number; dynamicHeight?: boolean; disableRipple?: boolean; disablePagination?: boolean; fitInkBarToContent?: boolean; stretchTabs?: boolean; color?: 'primary'|'accent'|'warn'; backgroundColor?: 'primary'|'accent'|'warn'|undefined; animationDuration?: string; ariaLabel?: string; ariaLabelledby?: string; };
|
|
113
|
-
tabs?: Array<{ id?: string; textLabel?: string; disabled?: boolean; labelClass?: string|string[]; bodyClass?: string|string[]; content?: any[]; widgets?: WidgetDefinition[] }>;
|
|
114
|
-
nav?: { links: Array<{ id?: string; label: string; disabled?: boolean; content?: any[]; widgets?: WidgetDefinition[] }>; selectedIndex?: number; disableRipple?: boolean; disablePagination?: boolean; fitInkBarToContent?: boolean; stretchTabs?: boolean; color?: 'primary'|'accent'|'warn'; backgroundColor?: 'primary'|'accent'|'warn'|undefined; animationDuration?: string; ariaLabel?: string; ariaLabelledby?: string };
|
|
146
|
+
tabs?: Array<{ id?: string; textLabel?: string; icon?: string; disabled?: boolean; visible?: boolean; labelClass?: string|string[]; bodyClass?: string|string[]; content?: any[]; widgets?: WidgetDefinition[] }>;
|
|
147
|
+
nav?: { links: Array<{ id?: string; label: string; icon?: string; disabled?: boolean; visible?: boolean; content?: any[]; widgets?: WidgetDefinition[] }>; selectedIndex?: number; disableRipple?: boolean; disablePagination?: boolean; fitInkBarToContent?: boolean; stretchTabs?: boolean; color?: 'primary'|'accent'|'warn'; backgroundColor?: 'primary'|'accent'|'warn'|undefined; animationDuration?: string; ariaLabel?: string; ariaLabelledby?: string };
|
|
115
148
|
}
|
|
116
149
|
```
|
|
117
150
|
|
|
@@ -153,6 +186,7 @@ Quick Setup
|
|
|
153
186
|
- **Editable targets:** `tab`, `tabLabel`, `tabIcon`, `tabContent`, `activeTab`, `visibility`, `disabledState` e `layout`.
|
|
154
187
|
- **Operation families:** `tab.add`, `tab.remove`, `tab.label.set`, `tab.icon.set`, `tab.order.set`, `tab.disabled.set`, `tab.visible.set`, `tab.active.set`, `layout.variant.set` e `tab.content.set`.
|
|
155
188
|
- **Validation:** ids de abas/links devem ser estáveis e únicos, remoção destrutiva exige confirmação, `group` e `nav` não devem virar modos primários concorrentes, e o round-trip precisa preservar ordem, ids e selected index.
|
|
189
|
+
- **Runtime/editor parity:** `tabs[].icon`, `tabs[].visible`, `nav.links[].icon` e `nav.links[].visible` são campos canônicos editáveis; itens com `visible: false` não são renderizados na navegação.
|
|
156
190
|
- **Registry projection:** o manifesto é exportado no `public-api` e projetado em `components['praxis-tabs'].authoringManifest` pelo AI Registry.
|
|
157
191
|
|
|
158
192
|
## Eventos e Conexões
|
|
@@ -784,6 +784,7 @@ class PraxisTabsConfigEditor {
|
|
|
784
784
|
this.editedConfig.tabs.push({
|
|
785
785
|
id: `tab${(this.editedConfig.tabs.length + 1)}`,
|
|
786
786
|
textLabel: this.t('defaults.newTabLabel', 'New Tab'),
|
|
787
|
+
visible: true,
|
|
787
788
|
});
|
|
788
789
|
this.onAppearanceChange();
|
|
789
790
|
}
|
|
@@ -859,6 +860,7 @@ class PraxisTabsConfigEditor {
|
|
|
859
860
|
this.nav.links.push({
|
|
860
861
|
id: `link${this.nav.links.length + 1}`,
|
|
861
862
|
label: this.t('defaults.newLinkLabel', 'New Link'),
|
|
863
|
+
visible: true,
|
|
862
864
|
});
|
|
863
865
|
this.onAppearanceChange();
|
|
864
866
|
}
|
|
@@ -1293,6 +1295,9 @@ class PraxisTabsConfigEditor {
|
|
|
1293
1295
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1294
1296
|
<input matInput [(ngModel)]="tab.textLabel" (ngModelChange)="onAppearanceChange()" />
|
|
1295
1297
|
</mat-form-field>
|
|
1298
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.icon', 'Icone') }}</mat-label>
|
|
1299
|
+
<input matInput [(ngModel)]="tab.icon" (ngModelChange)="onAppearanceChange()" />
|
|
1300
|
+
</mat-form-field>
|
|
1296
1301
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.labelClass', 'Classe do rotulo') }}</mat-label>
|
|
1297
1302
|
<input matInput [(ngModel)]="tab.labelClass" (ngModelChange)="onAppearanceChange()" />
|
|
1298
1303
|
</mat-form-field>
|
|
@@ -1306,7 +1311,10 @@ class PraxisTabsConfigEditor {
|
|
|
1306
1311
|
<input matInput [(ngModel)]="tab.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
1307
1312
|
</mat-form-field>
|
|
1308
1313
|
</div>
|
|
1309
|
-
<
|
|
1314
|
+
<div class="editor-row">
|
|
1315
|
+
<mat-slide-toggle [(ngModel)]="tab.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disabled', 'Desativada') }}</mat-slide-toggle>
|
|
1316
|
+
<mat-slide-toggle [ngModel]="tab.visible !== false" (ngModelChange)="tab.visible = $event; onAppearanceChange()">{{ t('editor.toggles.visible', 'Visivel') }}</mat-slide-toggle>
|
|
1317
|
+
</div>
|
|
1310
1318
|
|
|
1311
1319
|
<!-- Widgets (componentes dinâmicos) -->
|
|
1312
1320
|
<div class="editor-divider editor-grid">
|
|
@@ -1384,9 +1392,13 @@ class PraxisTabsConfigEditor {
|
|
|
1384
1392
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1385
1393
|
<input matInput [(ngModel)]="l.label" (ngModelChange)="onAppearanceChange()" />
|
|
1386
1394
|
</mat-form-field>
|
|
1395
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.icon', 'Icone') }}</mat-label>
|
|
1396
|
+
<input matInput [(ngModel)]="l.icon" (ngModelChange)="onAppearanceChange()" />
|
|
1397
|
+
</mat-form-field>
|
|
1387
1398
|
</div>
|
|
1388
1399
|
<div class="editor-row">
|
|
1389
1400
|
<mat-slide-toggle [(ngModel)]="l.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.linkDisabled', 'Desativado') }}</mat-slide-toggle>
|
|
1401
|
+
<mat-slide-toggle [ngModel]="l.visible !== false" (ngModelChange)="l.visible = $event; onAppearanceChange()">{{ t('editor.toggles.visible', 'Visivel') }}</mat-slide-toggle>
|
|
1390
1402
|
<mat-slide-toggle [(ngModel)]="l.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1391
1403
|
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1392
1404
|
</div>
|
|
@@ -1797,6 +1809,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1797
1809
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1798
1810
|
<input matInput [(ngModel)]="tab.textLabel" (ngModelChange)="onAppearanceChange()" />
|
|
1799
1811
|
</mat-form-field>
|
|
1812
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.icon', 'Icone') }}</mat-label>
|
|
1813
|
+
<input matInput [(ngModel)]="tab.icon" (ngModelChange)="onAppearanceChange()" />
|
|
1814
|
+
</mat-form-field>
|
|
1800
1815
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.labelClass', 'Classe do rotulo') }}</mat-label>
|
|
1801
1816
|
<input matInput [(ngModel)]="tab.labelClass" (ngModelChange)="onAppearanceChange()" />
|
|
1802
1817
|
</mat-form-field>
|
|
@@ -1810,7 +1825,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1810
1825
|
<input matInput [(ngModel)]="tab.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
1811
1826
|
</mat-form-field>
|
|
1812
1827
|
</div>
|
|
1813
|
-
<
|
|
1828
|
+
<div class="editor-row">
|
|
1829
|
+
<mat-slide-toggle [(ngModel)]="tab.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disabled', 'Desativada') }}</mat-slide-toggle>
|
|
1830
|
+
<mat-slide-toggle [ngModel]="tab.visible !== false" (ngModelChange)="tab.visible = $event; onAppearanceChange()">{{ t('editor.toggles.visible', 'Visivel') }}</mat-slide-toggle>
|
|
1831
|
+
</div>
|
|
1814
1832
|
|
|
1815
1833
|
<!-- Widgets (componentes dinâmicos) -->
|
|
1816
1834
|
<div class="editor-divider editor-grid">
|
|
@@ -1888,9 +1906,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1888
1906
|
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1889
1907
|
<input matInput [(ngModel)]="l.label" (ngModelChange)="onAppearanceChange()" />
|
|
1890
1908
|
</mat-form-field>
|
|
1909
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.icon', 'Icone') }}</mat-label>
|
|
1910
|
+
<input matInput [(ngModel)]="l.icon" (ngModelChange)="onAppearanceChange()" />
|
|
1911
|
+
</mat-form-field>
|
|
1891
1912
|
</div>
|
|
1892
1913
|
<div class="editor-row">
|
|
1893
1914
|
<mat-slide-toggle [(ngModel)]="l.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.linkDisabled', 'Desativado') }}</mat-slide-toggle>
|
|
1915
|
+
<mat-slide-toggle [ngModel]="l.visible !== false" (ngModelChange)="l.visible = $event; onAppearanceChange()">{{ t('editor.toggles.visible', 'Visivel') }}</mat-slide-toggle>
|
|
1894
1916
|
<mat-slide-toggle [(ngModel)]="l.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1895
1917
|
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1896
1918
|
</div>
|
|
@@ -2372,6 +2394,12 @@ class PraxisTabs {
|
|
|
2372
2394
|
config = null;
|
|
2373
2395
|
tabsId;
|
|
2374
2396
|
componentInstanceId;
|
|
2397
|
+
set selectedIndex(index) {
|
|
2398
|
+
if (index == null)
|
|
2399
|
+
return;
|
|
2400
|
+
this.controlledSelectedIndex = index;
|
|
2401
|
+
this.applySelectedIndex(index, false, false);
|
|
2402
|
+
}
|
|
2375
2403
|
enableCustomization = false;
|
|
2376
2404
|
form = null;
|
|
2377
2405
|
context = null;
|
|
@@ -2388,6 +2416,7 @@ class PraxisTabs {
|
|
|
2388
2416
|
selectedIndexSignal = signal(0, ...(ngDevMode ? [{ debugName: "selectedIndexSignal" }] : []));
|
|
2389
2417
|
groupLoaded = new Set();
|
|
2390
2418
|
navLoaded = new Set();
|
|
2419
|
+
controlledSelectedIndex;
|
|
2391
2420
|
destroy$ = new Subject();
|
|
2392
2421
|
widgetDefinitionCache = new WeakMap();
|
|
2393
2422
|
ngOnInit() {
|
|
@@ -2400,6 +2429,7 @@ class PraxisTabs {
|
|
|
2400
2429
|
this.config = stored;
|
|
2401
2430
|
}
|
|
2402
2431
|
this.syncSelectionFromConfig();
|
|
2432
|
+
this.reapplyControlledSelectedIndex();
|
|
2403
2433
|
});
|
|
2404
2434
|
}
|
|
2405
2435
|
}
|
|
@@ -2409,6 +2439,7 @@ class PraxisTabs {
|
|
|
2409
2439
|
this.syncSelectionFromConfig();
|
|
2410
2440
|
// Persist when tabsId provided
|
|
2411
2441
|
this.persistConfig(this.config);
|
|
2442
|
+
this.reapplyControlledSelectedIndex();
|
|
2412
2443
|
}
|
|
2413
2444
|
}
|
|
2414
2445
|
ngOnDestroy() {
|
|
@@ -2427,23 +2458,39 @@ class PraxisTabs {
|
|
|
2427
2458
|
getNavActive(i) {
|
|
2428
2459
|
return this.currentNavIndex() === i;
|
|
2429
2460
|
}
|
|
2461
|
+
visibleNavLinkEntries() {
|
|
2462
|
+
return (this.config?.nav?.links ?? [])
|
|
2463
|
+
.map((link, index) => ({ link, index }))
|
|
2464
|
+
.filter((entry) => entry.link.visible !== false);
|
|
2465
|
+
}
|
|
2466
|
+
visibleTabEntries() {
|
|
2467
|
+
return (this.config?.tabs ?? [])
|
|
2468
|
+
.map((tab, index) => ({ tab, index }))
|
|
2469
|
+
.filter((entry) => entry.tab.visible !== false);
|
|
2470
|
+
}
|
|
2471
|
+
selectedVisibleNavIndex() {
|
|
2472
|
+
const entries = this.visibleNavLinkEntries();
|
|
2473
|
+
const index = entries.findIndex((entry) => entry.index === this.currentNavIndex());
|
|
2474
|
+
return index >= 0 ? index : 0;
|
|
2475
|
+
}
|
|
2476
|
+
selectedVisibleTabIndex() {
|
|
2477
|
+
const entries = this.visibleTabEntries();
|
|
2478
|
+
const index = entries.findIndex((entry) => entry.index === this.selectedIndexSignal());
|
|
2479
|
+
return index >= 0 ? index : 0;
|
|
2480
|
+
}
|
|
2481
|
+
onVisibleTabIndexChange(index) {
|
|
2482
|
+
const entry = this.visibleTabEntries()[index];
|
|
2483
|
+
if (!entry)
|
|
2484
|
+
return;
|
|
2485
|
+
this.onSelectedIndexChange(entry.index);
|
|
2486
|
+
}
|
|
2430
2487
|
onNavClick(i) {
|
|
2431
2488
|
if (!this.config?.nav?.links?.length)
|
|
2432
2489
|
return;
|
|
2433
2490
|
const linksCount = this.config.nav.links.length;
|
|
2434
2491
|
if (i < 0 || i >= linksCount)
|
|
2435
2492
|
return;
|
|
2436
|
-
this.
|
|
2437
|
-
this.config = produce(this.config, (draft) => {
|
|
2438
|
-
if (!draft.nav)
|
|
2439
|
-
return;
|
|
2440
|
-
draft.nav.selectedIndex = i;
|
|
2441
|
-
});
|
|
2442
|
-
this.persistConfig(this.config);
|
|
2443
|
-
// Lazy: mark as loaded
|
|
2444
|
-
this.navLoaded.add(i);
|
|
2445
|
-
// Emit as index change for consumers to track
|
|
2446
|
-
this.selectedIndexChange.emit(i);
|
|
2493
|
+
this.applySelectedIndex(i, true);
|
|
2447
2494
|
}
|
|
2448
2495
|
onNavDrop(event) {
|
|
2449
2496
|
if (!this.config?.nav?.links)
|
|
@@ -2491,10 +2538,39 @@ class PraxisTabs {
|
|
|
2491
2538
|
});
|
|
2492
2539
|
this.persistConfig(this.config);
|
|
2493
2540
|
}
|
|
2541
|
+
onVisibleNavDrop(event) {
|
|
2542
|
+
const entries = this.visibleNavLinkEntries();
|
|
2543
|
+
const previous = entries[event.previousIndex];
|
|
2544
|
+
const current = entries[event.currentIndex];
|
|
2545
|
+
if (!previous || !current)
|
|
2546
|
+
return;
|
|
2547
|
+
this.onNavDrop({
|
|
2548
|
+
...event,
|
|
2549
|
+
previousIndex: previous.index,
|
|
2550
|
+
currentIndex: current.index,
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2494
2553
|
onSelectedIndexChange(index) {
|
|
2554
|
+
this.applySelectedIndex(index, true);
|
|
2555
|
+
}
|
|
2556
|
+
applySelectedIndex(index, emit, persist = true) {
|
|
2557
|
+
if (this.isNavMode() && this.config) {
|
|
2558
|
+
const selected = this.clampIndex(index, this.config?.nav?.links?.length ?? 0);
|
|
2559
|
+
this.currentNavIndex.set(selected);
|
|
2560
|
+
this.config = produce(this.config, (draft) => {
|
|
2561
|
+
draft.nav.selectedIndex = selected;
|
|
2562
|
+
});
|
|
2563
|
+
if (persist) {
|
|
2564
|
+
this.persistConfig(this.config);
|
|
2565
|
+
}
|
|
2566
|
+
this.navLoaded.add(selected);
|
|
2567
|
+
if (emit) {
|
|
2568
|
+
this.selectedIndexChange.emit(selected);
|
|
2569
|
+
}
|
|
2570
|
+
return;
|
|
2571
|
+
}
|
|
2495
2572
|
const selected = this.clampIndex(index, this.config?.tabs?.length ?? 0);
|
|
2496
2573
|
this.selectedIndexSignal.set(selected);
|
|
2497
|
-
// Update config immutably
|
|
2498
2574
|
if (this.config) {
|
|
2499
2575
|
this.config = produce(this.config, (draft) => {
|
|
2500
2576
|
if (!draft.group) {
|
|
@@ -2504,11 +2580,20 @@ class PraxisTabs {
|
|
|
2504
2580
|
draft.group.selectedIndex = selected;
|
|
2505
2581
|
}
|
|
2506
2582
|
});
|
|
2507
|
-
|
|
2583
|
+
if (persist) {
|
|
2584
|
+
this.persistConfig(this.config);
|
|
2585
|
+
}
|
|
2508
2586
|
}
|
|
2509
|
-
// Lazy: mark as loaded
|
|
2510
2587
|
this.groupLoaded.add(selected);
|
|
2511
|
-
|
|
2588
|
+
if (emit) {
|
|
2589
|
+
this.selectedIndexChange.emit(selected);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
reapplyControlledSelectedIndex() {
|
|
2593
|
+
if (this.controlledSelectedIndex == null) {
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
this.applySelectedIndex(this.controlledSelectedIndex, false, false);
|
|
2512
2597
|
}
|
|
2513
2598
|
closeTab(index) {
|
|
2514
2599
|
if (!this.config?.tabs)
|
|
@@ -2764,10 +2849,16 @@ class PraxisTabs {
|
|
|
2764
2849
|
return !this.isLazy() || this.navLoaded.has(index) || this.currentNavIndex() === index;
|
|
2765
2850
|
}
|
|
2766
2851
|
isEmptyGlobal() {
|
|
2767
|
-
const hasTabs =
|
|
2768
|
-
const hasLinks =
|
|
2852
|
+
const hasTabs = this.visibleTabEntries().length > 0;
|
|
2853
|
+
const hasLinks = this.visibleNavLinkEntries().length > 0;
|
|
2769
2854
|
return !(hasTabs || hasLinks);
|
|
2770
2855
|
}
|
|
2856
|
+
trackVisibleNavLink(index, entry) {
|
|
2857
|
+
return entry.link.id || `${entry.link.label || 'nav-link'}:${entry.index ?? index}`;
|
|
2858
|
+
}
|
|
2859
|
+
trackVisibleTab(index, entry) {
|
|
2860
|
+
return entry.tab.id || entry.tab.textLabel || `tab:${entry.index ?? index}`;
|
|
2861
|
+
}
|
|
2771
2862
|
trackNavLink(index, link) {
|
|
2772
2863
|
return link.id || `${link.label || 'nav-link'}:${index}`;
|
|
2773
2864
|
}
|
|
@@ -2952,7 +3043,7 @@ class PraxisTabs {
|
|
|
2952
3043
|
return JSON.parse(JSON.stringify(widget));
|
|
2953
3044
|
}
|
|
2954
3045
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2955
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", widgetEvent: "widgetEvent" }, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], usesOnChanges: true, ngImport: i0, template: `
|
|
3046
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", selectedIndex: "selectedIndex", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", widgetEvent: "widgetEvent" }, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], usesOnChanges: true, ngImport: i0, template: `
|
|
2956
3047
|
<div
|
|
2957
3048
|
class="praxis-tabs-root"
|
|
2958
3049
|
[class.density-compact]="config?.appearance?.density === 'compact'"
|
|
@@ -2995,13 +3086,13 @@ class PraxisTabs {
|
|
|
2995
3086
|
cdkDropList
|
|
2996
3087
|
cdkDropListOrientation="horizontal"
|
|
2997
3088
|
[cdkDropListDisabled]="!config?.behavior?.reorderable"
|
|
2998
|
-
(cdkDropListDropped)="
|
|
3089
|
+
(cdkDropListDropped)="onVisibleNavDrop($event)"
|
|
2999
3090
|
[disablePagination]="config?.nav?.disablePagination"
|
|
3000
3091
|
[fitInkBarToContent]="config?.nav?.fitInkBarToContent"
|
|
3001
3092
|
[mat-stretch-tabs]="config?.nav?.stretchTabs"
|
|
3002
3093
|
[color]="config?.nav?.color"
|
|
3003
3094
|
[backgroundColor]="config?.nav?.backgroundColor"
|
|
3004
|
-
[selectedIndex]="
|
|
3095
|
+
[selectedIndex]="selectedVisibleNavIndex()"
|
|
3005
3096
|
[attr.aria-label]="config?.nav?.ariaLabel || config?.group?.ariaLabel || null"
|
|
3006
3097
|
[attr.aria-labelledby]="config?.nav?.ariaLabelledby || config?.group?.ariaLabelledby || null"
|
|
3007
3098
|
[animationDuration]="effectiveAnimationDuration()"
|
|
@@ -3010,21 +3101,22 @@ class PraxisTabs {
|
|
|
3010
3101
|
>
|
|
3011
3102
|
<a
|
|
3012
3103
|
mat-tab-link
|
|
3013
|
-
*ngFor="let
|
|
3104
|
+
*ngFor="let entry of visibleNavLinkEntries(); let i = index; trackBy: trackVisibleNavLink"
|
|
3014
3105
|
cdkDrag
|
|
3015
3106
|
[cdkDragDisabled]="!config?.behavior?.reorderable"
|
|
3016
3107
|
cdkDragLockAxis="x"
|
|
3017
|
-
[active]="getNavActive(
|
|
3018
|
-
[disabled]="link.disabled"
|
|
3019
|
-
[disableRipple]="config?.nav?.disableRipple || link.disableRipple"
|
|
3020
|
-
[fitInkBarToContent]="link.fitInkBarToContent || false"
|
|
3021
|
-
[id]="link.id || ''"
|
|
3022
|
-
(click)="onNavClick(
|
|
3108
|
+
[active]="getNavActive(entry.index)"
|
|
3109
|
+
[disabled]="entry.link.disabled"
|
|
3110
|
+
[disableRipple]="config?.nav?.disableRipple || entry.link.disableRipple"
|
|
3111
|
+
[fitInkBarToContent]="entry.link.fitInkBarToContent || false"
|
|
3112
|
+
[id]="entry.link.id || ''"
|
|
3113
|
+
(click)="onNavClick(entry.index)"
|
|
3023
3114
|
>
|
|
3024
3115
|
<span *ngIf="config?.behavior?.reorderable" class="drag-handle" cdkDragHandle>
|
|
3025
3116
|
<mat-icon fontIcon="drag_indicator"></mat-icon>
|
|
3026
3117
|
</span>
|
|
3027
|
-
|
|
3118
|
+
<mat-icon *ngIf="entry.link.icon" class="tab-label-icon" [praxisIcon]="entry.link.icon"></mat-icon>
|
|
3119
|
+
{{ entry.link.label }}
|
|
3028
3120
|
</a>
|
|
3029
3121
|
</nav>
|
|
3030
3122
|
|
|
@@ -3074,7 +3166,7 @@ class PraxisTabs {
|
|
|
3074
3166
|
[fitInkBarToContent]="config?.group?.fitInkBarToContent"
|
|
3075
3167
|
[headerPosition]="config?.group?.headerPosition ?? 'above'"
|
|
3076
3168
|
[preserveContent]="config?.group?.preserveContent"
|
|
3077
|
-
[selectedIndex]="
|
|
3169
|
+
[selectedIndex]="selectedVisibleTabIndex()"
|
|
3078
3170
|
[mat-stretch-tabs]="config?.group?.stretchTabs"
|
|
3079
3171
|
[mat-align-tabs]="config?.group?.alignTabs || 'start'"
|
|
3080
3172
|
[color]="config?.group?.color"
|
|
@@ -3084,26 +3176,27 @@ class PraxisTabs {
|
|
|
3084
3176
|
[attr.aria-labelledby]="config?.group?.ariaLabelledby || null"
|
|
3085
3177
|
(animationDone)="animationDone.emit()"
|
|
3086
3178
|
(focusChange)="focusChange.emit($event)"
|
|
3087
|
-
(selectedIndexChange)="
|
|
3179
|
+
(selectedIndexChange)="onVisibleTabIndexChange($event)"
|
|
3088
3180
|
(selectedTabChange)="selectedTabChange.emit($event)"
|
|
3089
3181
|
class="praxis-tabs-group"
|
|
3090
3182
|
>
|
|
3091
3183
|
<mat-tab
|
|
3092
|
-
*ngFor="let
|
|
3093
|
-
[disabled]="tab.disabled"
|
|
3094
|
-
[labelClass]="tab.labelClass ?? ''"
|
|
3095
|
-
[bodyClass]="tab.bodyClass ?? ''"
|
|
3096
|
-
[id]="tab.id || ''"
|
|
3097
|
-
[attr.aria-label]="tab.ariaLabel || null"
|
|
3098
|
-
[attr.aria-labelledby]="tab.ariaLabelledby || null"
|
|
3184
|
+
*ngFor="let entry of visibleTabEntries(); let i = index; trackBy: trackVisibleTab"
|
|
3185
|
+
[disabled]="entry.tab.disabled"
|
|
3186
|
+
[labelClass]="entry.tab.labelClass ?? ''"
|
|
3187
|
+
[bodyClass]="entry.tab.bodyClass ?? ''"
|
|
3188
|
+
[id]="entry.tab.id || ''"
|
|
3189
|
+
[attr.aria-label]="entry.tab.ariaLabel || null"
|
|
3190
|
+
[attr.aria-labelledby]="entry.tab.ariaLabelledby || null"
|
|
3099
3191
|
>
|
|
3100
3192
|
<ng-template mat-tab-label>
|
|
3101
|
-
<
|
|
3193
|
+
<mat-icon *ngIf="entry.tab.icon" class="tab-label-icon" [praxisIcon]="entry.tab.icon"></mat-icon>
|
|
3194
|
+
<span>{{ entry.tab.textLabel }}</span>
|
|
3102
3195
|
<button
|
|
3103
3196
|
*ngIf="config?.behavior?.closeable"
|
|
3104
3197
|
mat-icon-button
|
|
3105
3198
|
type="button"
|
|
3106
|
-
(click)="closeTab(
|
|
3199
|
+
(click)="closeTab(entry.index); $event.stopPropagation()"
|
|
3107
3200
|
(keydown.enter)="$event.stopPropagation()"
|
|
3108
3201
|
(keydown.space)="$event.stopPropagation()"
|
|
3109
3202
|
[attr.aria-label]="t('chrome.closeTab', 'Fechar aba')"
|
|
@@ -3114,10 +3207,10 @@ class PraxisTabs {
|
|
|
3114
3207
|
<button
|
|
3115
3208
|
mat-icon-button
|
|
3116
3209
|
type="button"
|
|
3117
|
-
(click)="moveTab(
|
|
3210
|
+
(click)="moveTab(entry.index, -1); $event.stopPropagation()"
|
|
3118
3211
|
(keydown.enter)="$event.stopPropagation()"
|
|
3119
3212
|
(keydown.space)="$event.stopPropagation()"
|
|
3120
|
-
[disabled]="
|
|
3213
|
+
[disabled]="entry.index===0"
|
|
3121
3214
|
[attr.aria-label]="t('chrome.moveTabLeft', 'Mover aba para esquerda')"
|
|
3122
3215
|
>
|
|
3123
3216
|
<mat-icon fontIcon="arrow_back"></mat-icon>
|
|
@@ -3125,10 +3218,10 @@ class PraxisTabs {
|
|
|
3125
3218
|
<button
|
|
3126
3219
|
mat-icon-button
|
|
3127
3220
|
type="button"
|
|
3128
|
-
(click)="moveTab(
|
|
3221
|
+
(click)="moveTab(entry.index, 1); $event.stopPropagation()"
|
|
3129
3222
|
(keydown.enter)="$event.stopPropagation()"
|
|
3130
3223
|
(keydown.space)="$event.stopPropagation()"
|
|
3131
|
-
[disabled]="
|
|
3224
|
+
[disabled]="entry.index===(config?.tabs?.length||1)-1"
|
|
3132
3225
|
[attr.aria-label]="t('chrome.moveTabRight', 'Mover aba para direita')"
|
|
3133
3226
|
>
|
|
3134
3227
|
<mat-icon fontIcon="arrow_forward"></mat-icon>
|
|
@@ -3137,20 +3230,20 @@ class PraxisTabs {
|
|
|
3137
3230
|
</ng-template>
|
|
3138
3231
|
|
|
3139
3232
|
<ng-template matTabContent>
|
|
3140
|
-
<ng-container *ngIf="(tab.content?.length || tab.widgets?.length) && groupContentReady(
|
|
3141
|
-
<ng-container *ngIf="tab.content && form">
|
|
3233
|
+
<ng-container *ngIf="(entry.tab.content?.length || entry.tab.widgets?.length) && groupContentReady(entry.index); else emptyTab">
|
|
3234
|
+
<ng-container *ngIf="entry.tab.content && form">
|
|
3142
3235
|
<ng-container
|
|
3143
3236
|
dynamicFieldLoader
|
|
3144
|
-
[fields]="tab.content || []"
|
|
3237
|
+
[fields]="entry.tab.content || []"
|
|
3145
3238
|
[formGroup]="form!"
|
|
3146
3239
|
></ng-container>
|
|
3147
3240
|
</ng-container>
|
|
3148
|
-
<ng-container *ngIf="tab.widgets?.length">
|
|
3149
|
-
<ng-container *ngFor="let w of tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
3241
|
+
<ng-container *ngIf="entry.tab.widgets?.length">
|
|
3242
|
+
<ng-container *ngFor="let w of entry.tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
3150
3243
|
<ng-container
|
|
3151
3244
|
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
3152
3245
|
[context]="context || {}"
|
|
3153
|
-
(widgetEvent)="emitWidgetEvent(tabEventPath(tab.id,
|
|
3246
|
+
(widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
|
|
3154
3247
|
></ng-container>
|
|
3155
3248
|
</ng-container>
|
|
3156
3249
|
</ng-container>
|
|
@@ -3191,7 +3284,7 @@ class PraxisTabs {
|
|
|
3191
3284
|
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
|
|
3192
3285
|
</button>
|
|
3193
3286
|
</div>
|
|
3194
|
-
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i3$1.MatTabContent, selector: "[matTabContent]" }, { kind: "directive", type: i3$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i3$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i3$1.MatTabNav, selector: "[mat-tab-nav-bar]", inputs: ["fitInkBarToContent", "mat-stretch-tabs", "animationDuration", "backgroundColor", "disableRipple", "color", "tabPanel"], exportAs: ["matTabNavBar", "matTabNav"] }, { kind: "component", type: i3$1.MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: ["id"], exportAs: ["matTabNavPanel"] }, { kind: "component", type: i3$1.MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: ["active", "disabled", "disableRipple", "tabIndex", "id"], exportAs: ["matTabLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3287
|
+
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}.tab-label-icon{font-size:18px;width:18px;height:18px;margin-right:6px;vertical-align:middle}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i3$1.MatTabContent, selector: "[matTabContent]" }, { kind: "directive", type: i3$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i3$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i3$1.MatTabNav, selector: "[mat-tab-nav-bar]", inputs: ["fitInkBarToContent", "mat-stretch-tabs", "animationDuration", "backgroundColor", "disableRipple", "color", "tabPanel"], exportAs: ["matTabNavBar", "matTabNav"] }, { kind: "component", type: i3$1.MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: ["id"], exportAs: ["matTabNavPanel"] }, { kind: "component", type: i3$1.MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: ["active", "disabled", "disableRipple", "tabIndex", "id"], exportAs: ["matTabLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3195
3288
|
}
|
|
3196
3289
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabs, decorators: [{
|
|
3197
3290
|
type: Component,
|
|
@@ -3251,13 +3344,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3251
3344
|
cdkDropList
|
|
3252
3345
|
cdkDropListOrientation="horizontal"
|
|
3253
3346
|
[cdkDropListDisabled]="!config?.behavior?.reorderable"
|
|
3254
|
-
(cdkDropListDropped)="
|
|
3347
|
+
(cdkDropListDropped)="onVisibleNavDrop($event)"
|
|
3255
3348
|
[disablePagination]="config?.nav?.disablePagination"
|
|
3256
3349
|
[fitInkBarToContent]="config?.nav?.fitInkBarToContent"
|
|
3257
3350
|
[mat-stretch-tabs]="config?.nav?.stretchTabs"
|
|
3258
3351
|
[color]="config?.nav?.color"
|
|
3259
3352
|
[backgroundColor]="config?.nav?.backgroundColor"
|
|
3260
|
-
[selectedIndex]="
|
|
3353
|
+
[selectedIndex]="selectedVisibleNavIndex()"
|
|
3261
3354
|
[attr.aria-label]="config?.nav?.ariaLabel || config?.group?.ariaLabel || null"
|
|
3262
3355
|
[attr.aria-labelledby]="config?.nav?.ariaLabelledby || config?.group?.ariaLabelledby || null"
|
|
3263
3356
|
[animationDuration]="effectiveAnimationDuration()"
|
|
@@ -3266,21 +3359,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3266
3359
|
>
|
|
3267
3360
|
<a
|
|
3268
3361
|
mat-tab-link
|
|
3269
|
-
*ngFor="let
|
|
3362
|
+
*ngFor="let entry of visibleNavLinkEntries(); let i = index; trackBy: trackVisibleNavLink"
|
|
3270
3363
|
cdkDrag
|
|
3271
3364
|
[cdkDragDisabled]="!config?.behavior?.reorderable"
|
|
3272
3365
|
cdkDragLockAxis="x"
|
|
3273
|
-
[active]="getNavActive(
|
|
3274
|
-
[disabled]="link.disabled"
|
|
3275
|
-
[disableRipple]="config?.nav?.disableRipple || link.disableRipple"
|
|
3276
|
-
[fitInkBarToContent]="link.fitInkBarToContent || false"
|
|
3277
|
-
[id]="link.id || ''"
|
|
3278
|
-
(click)="onNavClick(
|
|
3366
|
+
[active]="getNavActive(entry.index)"
|
|
3367
|
+
[disabled]="entry.link.disabled"
|
|
3368
|
+
[disableRipple]="config?.nav?.disableRipple || entry.link.disableRipple"
|
|
3369
|
+
[fitInkBarToContent]="entry.link.fitInkBarToContent || false"
|
|
3370
|
+
[id]="entry.link.id || ''"
|
|
3371
|
+
(click)="onNavClick(entry.index)"
|
|
3279
3372
|
>
|
|
3280
3373
|
<span *ngIf="config?.behavior?.reorderable" class="drag-handle" cdkDragHandle>
|
|
3281
3374
|
<mat-icon fontIcon="drag_indicator"></mat-icon>
|
|
3282
3375
|
</span>
|
|
3283
|
-
|
|
3376
|
+
<mat-icon *ngIf="entry.link.icon" class="tab-label-icon" [praxisIcon]="entry.link.icon"></mat-icon>
|
|
3377
|
+
{{ entry.link.label }}
|
|
3284
3378
|
</a>
|
|
3285
3379
|
</nav>
|
|
3286
3380
|
|
|
@@ -3330,7 +3424,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3330
3424
|
[fitInkBarToContent]="config?.group?.fitInkBarToContent"
|
|
3331
3425
|
[headerPosition]="config?.group?.headerPosition ?? 'above'"
|
|
3332
3426
|
[preserveContent]="config?.group?.preserveContent"
|
|
3333
|
-
[selectedIndex]="
|
|
3427
|
+
[selectedIndex]="selectedVisibleTabIndex()"
|
|
3334
3428
|
[mat-stretch-tabs]="config?.group?.stretchTabs"
|
|
3335
3429
|
[mat-align-tabs]="config?.group?.alignTabs || 'start'"
|
|
3336
3430
|
[color]="config?.group?.color"
|
|
@@ -3340,26 +3434,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3340
3434
|
[attr.aria-labelledby]="config?.group?.ariaLabelledby || null"
|
|
3341
3435
|
(animationDone)="animationDone.emit()"
|
|
3342
3436
|
(focusChange)="focusChange.emit($event)"
|
|
3343
|
-
(selectedIndexChange)="
|
|
3437
|
+
(selectedIndexChange)="onVisibleTabIndexChange($event)"
|
|
3344
3438
|
(selectedTabChange)="selectedTabChange.emit($event)"
|
|
3345
3439
|
class="praxis-tabs-group"
|
|
3346
3440
|
>
|
|
3347
3441
|
<mat-tab
|
|
3348
|
-
*ngFor="let
|
|
3349
|
-
[disabled]="tab.disabled"
|
|
3350
|
-
[labelClass]="tab.labelClass ?? ''"
|
|
3351
|
-
[bodyClass]="tab.bodyClass ?? ''"
|
|
3352
|
-
[id]="tab.id || ''"
|
|
3353
|
-
[attr.aria-label]="tab.ariaLabel || null"
|
|
3354
|
-
[attr.aria-labelledby]="tab.ariaLabelledby || null"
|
|
3442
|
+
*ngFor="let entry of visibleTabEntries(); let i = index; trackBy: trackVisibleTab"
|
|
3443
|
+
[disabled]="entry.tab.disabled"
|
|
3444
|
+
[labelClass]="entry.tab.labelClass ?? ''"
|
|
3445
|
+
[bodyClass]="entry.tab.bodyClass ?? ''"
|
|
3446
|
+
[id]="entry.tab.id || ''"
|
|
3447
|
+
[attr.aria-label]="entry.tab.ariaLabel || null"
|
|
3448
|
+
[attr.aria-labelledby]="entry.tab.ariaLabelledby || null"
|
|
3355
3449
|
>
|
|
3356
3450
|
<ng-template mat-tab-label>
|
|
3357
|
-
<
|
|
3451
|
+
<mat-icon *ngIf="entry.tab.icon" class="tab-label-icon" [praxisIcon]="entry.tab.icon"></mat-icon>
|
|
3452
|
+
<span>{{ entry.tab.textLabel }}</span>
|
|
3358
3453
|
<button
|
|
3359
3454
|
*ngIf="config?.behavior?.closeable"
|
|
3360
3455
|
mat-icon-button
|
|
3361
3456
|
type="button"
|
|
3362
|
-
(click)="closeTab(
|
|
3457
|
+
(click)="closeTab(entry.index); $event.stopPropagation()"
|
|
3363
3458
|
(keydown.enter)="$event.stopPropagation()"
|
|
3364
3459
|
(keydown.space)="$event.stopPropagation()"
|
|
3365
3460
|
[attr.aria-label]="t('chrome.closeTab', 'Fechar aba')"
|
|
@@ -3370,10 +3465,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3370
3465
|
<button
|
|
3371
3466
|
mat-icon-button
|
|
3372
3467
|
type="button"
|
|
3373
|
-
(click)="moveTab(
|
|
3468
|
+
(click)="moveTab(entry.index, -1); $event.stopPropagation()"
|
|
3374
3469
|
(keydown.enter)="$event.stopPropagation()"
|
|
3375
3470
|
(keydown.space)="$event.stopPropagation()"
|
|
3376
|
-
[disabled]="
|
|
3471
|
+
[disabled]="entry.index===0"
|
|
3377
3472
|
[attr.aria-label]="t('chrome.moveTabLeft', 'Mover aba para esquerda')"
|
|
3378
3473
|
>
|
|
3379
3474
|
<mat-icon fontIcon="arrow_back"></mat-icon>
|
|
@@ -3381,10 +3476,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3381
3476
|
<button
|
|
3382
3477
|
mat-icon-button
|
|
3383
3478
|
type="button"
|
|
3384
|
-
(click)="moveTab(
|
|
3479
|
+
(click)="moveTab(entry.index, 1); $event.stopPropagation()"
|
|
3385
3480
|
(keydown.enter)="$event.stopPropagation()"
|
|
3386
3481
|
(keydown.space)="$event.stopPropagation()"
|
|
3387
|
-
[disabled]="
|
|
3482
|
+
[disabled]="entry.index===(config?.tabs?.length||1)-1"
|
|
3388
3483
|
[attr.aria-label]="t('chrome.moveTabRight', 'Mover aba para direita')"
|
|
3389
3484
|
>
|
|
3390
3485
|
<mat-icon fontIcon="arrow_forward"></mat-icon>
|
|
@@ -3393,20 +3488,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3393
3488
|
</ng-template>
|
|
3394
3489
|
|
|
3395
3490
|
<ng-template matTabContent>
|
|
3396
|
-
<ng-container *ngIf="(tab.content?.length || tab.widgets?.length) && groupContentReady(
|
|
3397
|
-
<ng-container *ngIf="tab.content && form">
|
|
3491
|
+
<ng-container *ngIf="(entry.tab.content?.length || entry.tab.widgets?.length) && groupContentReady(entry.index); else emptyTab">
|
|
3492
|
+
<ng-container *ngIf="entry.tab.content && form">
|
|
3398
3493
|
<ng-container
|
|
3399
3494
|
dynamicFieldLoader
|
|
3400
|
-
[fields]="tab.content || []"
|
|
3495
|
+
[fields]="entry.tab.content || []"
|
|
3401
3496
|
[formGroup]="form!"
|
|
3402
3497
|
></ng-container>
|
|
3403
3498
|
</ng-container>
|
|
3404
|
-
<ng-container *ngIf="tab.widgets?.length">
|
|
3405
|
-
<ng-container *ngFor="let w of tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
3499
|
+
<ng-container *ngIf="entry.tab.widgets?.length">
|
|
3500
|
+
<ng-container *ngFor="let w of entry.tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
3406
3501
|
<ng-container
|
|
3407
3502
|
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
3408
3503
|
[context]="context || {}"
|
|
3409
|
-
(widgetEvent)="emitWidgetEvent(tabEventPath(tab.id,
|
|
3504
|
+
(widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
|
|
3410
3505
|
></ng-container>
|
|
3411
3506
|
</ng-container>
|
|
3412
3507
|
</ng-container>
|
|
@@ -3447,7 +3542,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3447
3542
|
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
|
|
3448
3543
|
</button>
|
|
3449
3544
|
</div>
|
|
3450
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"] }]
|
|
3545
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}.tab-label-icon{font-size:18px;width:18px;height:18px;margin-right:6px;vertical-align:middle}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"] }]
|
|
3451
3546
|
}], propDecorators: { config: [{
|
|
3452
3547
|
type: Input
|
|
3453
3548
|
}], tabsId: [{
|
|
@@ -3455,6 +3550,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3455
3550
|
args: [{ required: true }]
|
|
3456
3551
|
}], componentInstanceId: [{
|
|
3457
3552
|
type: Input
|
|
3553
|
+
}], selectedIndex: [{
|
|
3554
|
+
type: Input
|
|
3458
3555
|
}], enableCustomization: [{
|
|
3459
3556
|
type: Input
|
|
3460
3557
|
}], form: [{
|
|
@@ -3504,6 +3601,19 @@ const PRAXIS_TABS_PORTS = [
|
|
|
3504
3601
|
description: 'Fragmento canonico de configuracao das tabs/nav e dos widgets internos.',
|
|
3505
3602
|
exposure: { public: true, group: 'config' },
|
|
3506
3603
|
},
|
|
3604
|
+
{
|
|
3605
|
+
id: 'selectedIndex',
|
|
3606
|
+
label: 'Indice selecionado',
|
|
3607
|
+
direction: 'input',
|
|
3608
|
+
semanticKind: 'value',
|
|
3609
|
+
schema: {
|
|
3610
|
+
id: 'number',
|
|
3611
|
+
kind: 'ts-type',
|
|
3612
|
+
ref: 'number',
|
|
3613
|
+
},
|
|
3614
|
+
description: 'Indice ativo de abas/nav para controle externo por composicao.',
|
|
3615
|
+
exposure: { public: true, group: 'state' },
|
|
3616
|
+
},
|
|
3507
3617
|
{
|
|
3508
3618
|
id: 'selectedIndexChange',
|
|
3509
3619
|
label: 'Troca de indice selecionado',
|
|
@@ -3554,6 +3664,12 @@ const PRAXIS_TABS_COMPONENT_METADATA = {
|
|
|
3554
3664
|
label: 'ID da instância',
|
|
3555
3665
|
description: 'Identificador opcional para múltiplas instâncias na mesma rota',
|
|
3556
3666
|
},
|
|
3667
|
+
{
|
|
3668
|
+
name: 'selectedIndex',
|
|
3669
|
+
type: 'number',
|
|
3670
|
+
label: 'Indice selecionado',
|
|
3671
|
+
description: 'Indice ativo de abas/nav controlavel externamente pela composicao',
|
|
3672
|
+
},
|
|
3557
3673
|
{
|
|
3558
3674
|
name: 'enableCustomization',
|
|
3559
3675
|
type: 'boolean',
|
|
@@ -3718,11 +3834,11 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3718
3834
|
editableTargets: [
|
|
3719
3835
|
{ kind: 'tab', resolver: 'tab-by-id-or-label', description: 'A group-mode tab in config.tabs[].' },
|
|
3720
3836
|
{ kind: 'tabLabel', resolver: 'tab-by-id-or-label', description: 'The text label of a group-mode tab.' },
|
|
3721
|
-
{ kind: 'tabIcon', resolver: 'tab-by-id-or-label', description: 'Icon metadata
|
|
3722
|
-
{ kind: 'tabContent', resolver: 'tab-
|
|
3837
|
+
{ kind: 'tabIcon', resolver: 'tab-by-id-or-label', description: 'Icon metadata rendered in a group tab label.' },
|
|
3838
|
+
{ kind: 'tabContent', resolver: 'tab-or-link-by-id', description: 'Dynamic fields or widgets hosted by a tab or nav link.' },
|
|
3723
3839
|
{ kind: 'activeTab', resolver: 'tab-index-or-id', description: 'Selected tab or nav link index.' },
|
|
3724
|
-
{ kind: 'visibility', resolver: 'tab-by-id
|
|
3725
|
-
{ kind: 'disabledState', resolver: 'tab-by-id
|
|
3840
|
+
{ kind: 'visibility', resolver: 'tab-or-link-by-id', description: 'Runtime visibility flag for a group tab or nav link.' },
|
|
3841
|
+
{ kind: 'disabledState', resolver: 'tab-or-link-by-id', description: 'Disabled state of a tab or nav link.' },
|
|
3726
3842
|
{ kind: 'layout', resolver: 'tabs-layout-config', description: 'Group/nav mode, header position, density, stretch and behavior settings.' },
|
|
3727
3843
|
],
|
|
3728
3844
|
operations: [
|
|
@@ -3735,8 +3851,10 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3735
3851
|
inputSchema: tabItemSchema,
|
|
3736
3852
|
effects: [{ kind: 'append-unique', path: 'tabs[]', key: 'id' }],
|
|
3737
3853
|
validators: ['tab-id-unique', 'tabs-mode-compatible', 'tab-content-valid'],
|
|
3738
|
-
|
|
3739
|
-
|
|
3854
|
+
destructive: false,
|
|
3855
|
+
requiresConfirmation: false,
|
|
3856
|
+
affectedPaths: ['tabs[]'],
|
|
3857
|
+
submissionImpact: 'config-only',
|
|
3740
3858
|
preconditions: ['config-initialized'],
|
|
3741
3859
|
},
|
|
3742
3860
|
{
|
|
@@ -3751,12 +3869,28 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3751
3869
|
replacementActiveTabId: { type: 'string' },
|
|
3752
3870
|
},
|
|
3753
3871
|
},
|
|
3754
|
-
effects: [
|
|
3872
|
+
effects: [
|
|
3873
|
+
{
|
|
3874
|
+
kind: 'compile-domain-patch',
|
|
3875
|
+
handler: 'tabs.remove-tab-and-reselect',
|
|
3876
|
+
handlerContract: {
|
|
3877
|
+
reads: ['tabs[]', 'group.selectedIndex'],
|
|
3878
|
+
writes: ['tabs[]', 'group.selectedIndex'],
|
|
3879
|
+
identityKeys: ['tabs[].id'],
|
|
3880
|
+
inputSchema: {
|
|
3881
|
+
type: 'object',
|
|
3882
|
+
properties: { replacementActiveTabId: { type: 'string' } },
|
|
3883
|
+
},
|
|
3884
|
+
failureModes: ['target-tab-missing', 'replacement-tab-missing', 'confirmation-missing'],
|
|
3885
|
+
description: 'Removes the target tab by stable id and reselects a safe replacement when the active/default tab is removed.',
|
|
3886
|
+
},
|
|
3887
|
+
},
|
|
3888
|
+
],
|
|
3755
3889
|
destructive: true,
|
|
3756
3890
|
requiresConfirmation: true,
|
|
3757
3891
|
validators: ['tab-exists', 'active-tab-removal-safe', 'tab-content-removal-confirmed'],
|
|
3758
3892
|
affectedPaths: ['tabs[]', 'group.selectedIndex'],
|
|
3759
|
-
submissionImpact:
|
|
3893
|
+
submissionImpact: 'config-only',
|
|
3760
3894
|
preconditions: ['config-initialized', 'target-tab-exists', 'confirmation-collected'],
|
|
3761
3895
|
},
|
|
3762
3896
|
{
|
|
@@ -3767,9 +3901,11 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3767
3901
|
target: { kind: 'tabLabel', resolver: 'tab-by-id-or-label', ambiguityPolicy: 'fail', required: true },
|
|
3768
3902
|
inputSchema: { type: 'object', required: ['textLabel'], properties: { textLabel: { type: 'string' } } },
|
|
3769
3903
|
effects: [{ kind: 'merge-by-key', path: 'tabs[]', key: 'id' }],
|
|
3904
|
+
destructive: false,
|
|
3905
|
+
requiresConfirmation: false,
|
|
3770
3906
|
validators: ['tab-exists', 'tab-label-valid'],
|
|
3771
3907
|
affectedPaths: ['tabs[].textLabel'],
|
|
3772
|
-
submissionImpact:
|
|
3908
|
+
submissionImpact: 'config-only',
|
|
3773
3909
|
preconditions: ['config-initialized', 'target-tab-exists'],
|
|
3774
3910
|
},
|
|
3775
3911
|
{
|
|
@@ -3780,9 +3916,11 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3780
3916
|
target: { kind: 'tabIcon', resolver: 'tab-by-id-or-label', ambiguityPolicy: 'fail', required: true },
|
|
3781
3917
|
inputSchema: { type: 'object', required: ['icon'], properties: { icon: { type: 'string' } } },
|
|
3782
3918
|
effects: [{ kind: 'merge-by-key', path: 'tabs[]', key: 'id' }],
|
|
3919
|
+
destructive: false,
|
|
3920
|
+
requiresConfirmation: false,
|
|
3783
3921
|
validators: ['tab-exists', 'tab-icon-valid'],
|
|
3784
3922
|
affectedPaths: ['tabs[].icon'],
|
|
3785
|
-
submissionImpact:
|
|
3923
|
+
submissionImpact: 'visual-only',
|
|
3786
3924
|
preconditions: ['config-initialized', 'target-tab-exists'],
|
|
3787
3925
|
},
|
|
3788
3926
|
{
|
|
@@ -3792,10 +3930,25 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3792
3930
|
targetKind: 'tab',
|
|
3793
3931
|
target: { kind: 'tab', resolver: 'tab-by-id-or-label', ambiguityPolicy: 'fail', required: true },
|
|
3794
3932
|
inputSchema: { type: 'object', required: ['beforeTabId'], properties: { beforeTabId: { type: 'string' } } },
|
|
3795
|
-
effects: [
|
|
3933
|
+
effects: [
|
|
3934
|
+
{
|
|
3935
|
+
kind: 'compile-domain-patch',
|
|
3936
|
+
handler: 'tabs.reorder-tab-and-preserve-selection',
|
|
3937
|
+
handlerContract: {
|
|
3938
|
+
reads: ['tabs[]', 'group.selectedIndex'],
|
|
3939
|
+
writes: ['tabs[]', 'group.selectedIndex'],
|
|
3940
|
+
identityKeys: ['tabs[].id'],
|
|
3941
|
+
inputSchema: { type: 'object', required: ['beforeTabId'], properties: { beforeTabId: { type: 'string' } } },
|
|
3942
|
+
failureModes: ['target-tab-missing', 'before-tab-missing', 'unstable-tab-id'],
|
|
3943
|
+
description: 'Reorders tabs by stable id and remaps group.selectedIndex when the selected tab crosses positions.',
|
|
3944
|
+
},
|
|
3945
|
+
},
|
|
3946
|
+
],
|
|
3947
|
+
destructive: false,
|
|
3948
|
+
requiresConfirmation: false,
|
|
3796
3949
|
validators: ['tab-exists', 'tab-order-deterministic'],
|
|
3797
3950
|
affectedPaths: ['tabs[]', 'group.selectedIndex'],
|
|
3798
|
-
submissionImpact:
|
|
3951
|
+
submissionImpact: 'config-only',
|
|
3799
3952
|
preconditions: ['config-initialized', 'target-tab-exists'],
|
|
3800
3953
|
},
|
|
3801
3954
|
{
|
|
@@ -3805,10 +3958,25 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3805
3958
|
targetKind: 'disabledState',
|
|
3806
3959
|
target: { kind: 'disabledState', resolver: 'tab-or-link-by-id', ambiguityPolicy: 'fail', required: true },
|
|
3807
3960
|
inputSchema: { type: 'object', required: ['disabled'], properties: { disabled: { type: 'boolean' } } },
|
|
3808
|
-
effects: [
|
|
3961
|
+
effects: [
|
|
3962
|
+
{
|
|
3963
|
+
kind: 'compile-domain-patch',
|
|
3964
|
+
handler: 'tabs.set-tab-or-link-disabled',
|
|
3965
|
+
handlerContract: {
|
|
3966
|
+
reads: ['tabs[]', 'nav.links[]', 'group.selectedIndex', 'nav.selectedIndex'],
|
|
3967
|
+
writes: ['tabs[].disabled', 'nav.links[].disabled'],
|
|
3968
|
+
identityKeys: ['tabs[].id', 'nav.links[].id'],
|
|
3969
|
+
inputSchema: { type: 'object', required: ['disabled'], properties: { disabled: { type: 'boolean' } } },
|
|
3970
|
+
failureModes: ['target-tab-or-link-missing', 'ambiguous-target', 'active-item-disabled-without-reselection'],
|
|
3971
|
+
description: 'Sets disabled on the resolved group tab or nav link without guessing between modes.',
|
|
3972
|
+
},
|
|
3973
|
+
},
|
|
3974
|
+
],
|
|
3975
|
+
destructive: false,
|
|
3976
|
+
requiresConfirmation: false,
|
|
3809
3977
|
validators: ['tab-or-link-exists', 'active-tab-disabled-safe'],
|
|
3810
3978
|
affectedPaths: ['tabs[].disabled', 'nav.links[].disabled'],
|
|
3811
|
-
submissionImpact:
|
|
3979
|
+
submissionImpact: 'config-only',
|
|
3812
3980
|
preconditions: ['config-initialized', 'target-tab-or-link-exists'],
|
|
3813
3981
|
},
|
|
3814
3982
|
{
|
|
@@ -3818,10 +3986,25 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3818
3986
|
targetKind: 'visibility',
|
|
3819
3987
|
target: { kind: 'visibility', resolver: 'tab-or-link-by-id', ambiguityPolicy: 'fail', required: true },
|
|
3820
3988
|
inputSchema: { type: 'object', required: ['visible'], properties: { visible: { type: 'boolean' } } },
|
|
3821
|
-
effects: [
|
|
3989
|
+
effects: [
|
|
3990
|
+
{
|
|
3991
|
+
kind: 'compile-domain-patch',
|
|
3992
|
+
handler: 'tabs.set-tab-or-link-visible',
|
|
3993
|
+
handlerContract: {
|
|
3994
|
+
reads: ['tabs[]', 'nav.links[]', 'group.selectedIndex', 'nav.selectedIndex'],
|
|
3995
|
+
writes: ['tabs[].visible', 'nav.links[].visible'],
|
|
3996
|
+
identityKeys: ['tabs[].id', 'nav.links[].id'],
|
|
3997
|
+
inputSchema: { type: 'object', required: ['visible'], properties: { visible: { type: 'boolean' } } },
|
|
3998
|
+
failureModes: ['target-tab-or-link-missing', 'ambiguous-target', 'active-item-hidden-without-reselection'],
|
|
3999
|
+
description: 'Sets visible on the resolved group tab or nav link and preserves deterministic visible-index mapping.',
|
|
4000
|
+
},
|
|
4001
|
+
},
|
|
4002
|
+
],
|
|
4003
|
+
destructive: false,
|
|
4004
|
+
requiresConfirmation: false,
|
|
3822
4005
|
validators: ['tab-or-link-exists', 'active-tab-visibility-safe'],
|
|
3823
4006
|
affectedPaths: ['tabs[].visible', 'nav.links[].visible'],
|
|
3824
|
-
submissionImpact:
|
|
4007
|
+
submissionImpact: 'config-only',
|
|
3825
4008
|
preconditions: ['config-initialized', 'target-tab-or-link-exists'],
|
|
3826
4009
|
},
|
|
3827
4010
|
{
|
|
@@ -3831,10 +4014,25 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3831
4014
|
targetKind: 'activeTab',
|
|
3832
4015
|
target: { kind: 'activeTab', resolver: 'tab-index-or-id', ambiguityPolicy: 'fail', required: true },
|
|
3833
4016
|
inputSchema: { type: 'object', required: ['selectedIndex'], properties: { selectedIndex: { type: 'number' }, tabId: { type: 'string' } } },
|
|
3834
|
-
effects: [
|
|
4017
|
+
effects: [
|
|
4018
|
+
{
|
|
4019
|
+
kind: 'compile-domain-patch',
|
|
4020
|
+
handler: 'tabs.set-active-item',
|
|
4021
|
+
handlerContract: {
|
|
4022
|
+
reads: ['tabs[]', 'nav.links[]', 'group.selectedIndex', 'nav.selectedIndex'],
|
|
4023
|
+
writes: ['group.selectedIndex', 'nav.selectedIndex'],
|
|
4024
|
+
identityKeys: ['tabs[].id', 'nav.links[].id'],
|
|
4025
|
+
inputSchema: { type: 'object', required: ['selectedIndex'], properties: { selectedIndex: { type: 'number' }, tabId: { type: 'string' } } },
|
|
4026
|
+
failureModes: ['target-tab-or-link-missing', 'selected-index-out-of-range', 'hidden-or-disabled-target'],
|
|
4027
|
+
description: 'Sets the active index for the current primary mode using either selectedIndex or a resolved tab/link id.',
|
|
4028
|
+
},
|
|
4029
|
+
},
|
|
4030
|
+
],
|
|
4031
|
+
destructive: false,
|
|
4032
|
+
requiresConfirmation: false,
|
|
3835
4033
|
validators: ['active-tab-exists', 'selected-index-in-range'],
|
|
3836
4034
|
affectedPaths: ['group.selectedIndex', 'nav.selectedIndex'],
|
|
3837
|
-
submissionImpact:
|
|
4035
|
+
submissionImpact: 'config-only',
|
|
3838
4036
|
preconditions: ['config-initialized', 'target-tab-or-link-exists'],
|
|
3839
4037
|
},
|
|
3840
4038
|
{
|
|
@@ -3856,9 +4054,11 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3856
4054
|
},
|
|
3857
4055
|
},
|
|
3858
4056
|
effects: [{ kind: 'merge-object', path: 'appearance' }, { kind: 'merge-object', path: 'group' }, { kind: 'merge-object', path: 'nav' }, { kind: 'merge-object', path: 'behavior' }],
|
|
4057
|
+
destructive: false,
|
|
4058
|
+
requiresConfirmation: false,
|
|
3859
4059
|
validators: ['tabs-mode-compatible', 'layout-values-valid', 'editor-runtime-round-trip'],
|
|
3860
4060
|
affectedPaths: ['appearance.density', 'group.headerPosition', 'group.alignTabs', 'group.stretchTabs', 'nav.stretchTabs', 'behavior.lazyLoad'],
|
|
3861
|
-
submissionImpact:
|
|
4061
|
+
submissionImpact: 'config-only',
|
|
3862
4062
|
preconditions: ['config-initialized'],
|
|
3863
4063
|
},
|
|
3864
4064
|
{
|
|
@@ -3868,10 +4068,25 @@ const PRAXIS_TABS_AUTHORING_MANIFEST = {
|
|
|
3868
4068
|
targetKind: 'tabContent',
|
|
3869
4069
|
target: { kind: 'tabContent', resolver: 'tab-or-link-by-id', ambiguityPolicy: 'fail', required: true },
|
|
3870
4070
|
inputSchema: tabPatchSchema,
|
|
3871
|
-
effects: [
|
|
4071
|
+
effects: [
|
|
4072
|
+
{
|
|
4073
|
+
kind: 'compile-domain-patch',
|
|
4074
|
+
handler: 'tabs.set-tab-or-link-content',
|
|
4075
|
+
handlerContract: {
|
|
4076
|
+
reads: ['tabs[]', 'nav.links[]'],
|
|
4077
|
+
writes: ['tabs[].content', 'tabs[].widgets', 'nav.links[].content', 'nav.links[].widgets'],
|
|
4078
|
+
identityKeys: ['tabs[].id', 'nav.links[].id'],
|
|
4079
|
+
inputSchema: tabPatchSchema,
|
|
4080
|
+
failureModes: ['target-tab-or-link-missing', 'invalid-dynamic-field-content', 'invalid-widget-definition'],
|
|
4081
|
+
description: 'Updates content/widgets only on the resolved group tab or nav link while preserving nested widget identity.',
|
|
4082
|
+
},
|
|
4083
|
+
},
|
|
4084
|
+
],
|
|
4085
|
+
destructive: false,
|
|
4086
|
+
requiresConfirmation: false,
|
|
3872
4087
|
validators: ['tab-or-link-exists', 'tab-content-valid', 'widget-event-delegated'],
|
|
3873
4088
|
affectedPaths: ['tabs[].content', 'tabs[].widgets', 'nav.links[].content', 'nav.links[].widgets'],
|
|
3874
|
-
submissionImpact:
|
|
4089
|
+
submissionImpact: 'config-only',
|
|
3875
4090
|
preconditions: ['config-initialized', 'target-tab-or-link-exists'],
|
|
3876
4091
|
},
|
|
3877
4092
|
],
|
package/index.d.ts
CHANGED
|
@@ -81,9 +81,11 @@ interface TabMetadata {
|
|
|
81
81
|
ariaLabel?: string;
|
|
82
82
|
ariaLabelledby?: string;
|
|
83
83
|
textLabel?: string;
|
|
84
|
+
icon?: string;
|
|
84
85
|
labelClass?: string | string[];
|
|
85
86
|
bodyClass?: string | string[];
|
|
86
87
|
disabled?: boolean;
|
|
88
|
+
visible?: boolean;
|
|
87
89
|
content?: any[];
|
|
88
90
|
widgets?: WidgetDefinition[];
|
|
89
91
|
isActive?: boolean;
|
|
@@ -106,8 +108,10 @@ interface TabNavMetadata {
|
|
|
106
108
|
interface TabLinkMetadata {
|
|
107
109
|
id?: string;
|
|
108
110
|
label: string;
|
|
111
|
+
icon?: string;
|
|
109
112
|
active?: boolean;
|
|
110
113
|
disabled?: boolean;
|
|
114
|
+
visible?: boolean;
|
|
111
115
|
disableRipple?: boolean;
|
|
112
116
|
fitInkBarToContent?: boolean;
|
|
113
117
|
content?: any[];
|
|
@@ -140,6 +144,7 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
140
144
|
config: TabsMetadata | null;
|
|
141
145
|
tabsId: string;
|
|
142
146
|
componentInstanceId?: string;
|
|
147
|
+
set selectedIndex(index: number | null | undefined);
|
|
143
148
|
enableCustomization: boolean;
|
|
144
149
|
form: FormGroup | null;
|
|
145
150
|
context: Record<string, any> | null;
|
|
@@ -155,6 +160,7 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
155
160
|
protected selectedIndexSignal: i0.WritableSignal<number>;
|
|
156
161
|
private groupLoaded;
|
|
157
162
|
private navLoaded;
|
|
163
|
+
private controlledSelectedIndex?;
|
|
158
164
|
private readonly destroy$;
|
|
159
165
|
private readonly widgetDefinitionCache;
|
|
160
166
|
ngOnInit(): void;
|
|
@@ -163,9 +169,23 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
163
169
|
isNavMode(): boolean;
|
|
164
170
|
effectiveAnimationDuration(): string;
|
|
165
171
|
getNavActive(i: number): boolean;
|
|
172
|
+
protected visibleNavLinkEntries(): Array<{
|
|
173
|
+
link: TabLinkMetadata;
|
|
174
|
+
index: number;
|
|
175
|
+
}>;
|
|
176
|
+
protected visibleTabEntries(): Array<{
|
|
177
|
+
tab: TabMetadata;
|
|
178
|
+
index: number;
|
|
179
|
+
}>;
|
|
180
|
+
protected selectedVisibleNavIndex(): number;
|
|
181
|
+
protected selectedVisibleTabIndex(): number;
|
|
182
|
+
protected onVisibleTabIndexChange(index: number): void;
|
|
166
183
|
onNavClick(i: number): void;
|
|
167
184
|
onNavDrop(event: CdkDragDrop<any>): void;
|
|
185
|
+
protected onVisibleNavDrop(event: CdkDragDrop<any>): void;
|
|
168
186
|
onSelectedIndexChange(index: number): void;
|
|
187
|
+
private applySelectedIndex;
|
|
188
|
+
private reapplyControlledSelectedIndex;
|
|
169
189
|
closeTab(index: number): void;
|
|
170
190
|
moveTab(index: number, delta: number): void;
|
|
171
191
|
openEditor(): void;
|
|
@@ -187,6 +207,14 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
187
207
|
protected groupContentReady(index: number): boolean;
|
|
188
208
|
protected navContentReady(index: number): boolean;
|
|
189
209
|
protected isEmptyGlobal(): boolean;
|
|
210
|
+
protected trackVisibleNavLink(index: number, entry: {
|
|
211
|
+
link: TabLinkMetadata;
|
|
212
|
+
index: number;
|
|
213
|
+
}): string;
|
|
214
|
+
protected trackVisibleTab(index: number, entry: {
|
|
215
|
+
tab: TabMetadata;
|
|
216
|
+
index: number;
|
|
217
|
+
}): string;
|
|
190
218
|
protected trackNavLink(index: number, link: TabLinkMetadata): string;
|
|
191
219
|
protected trackTab(index: number, tab: TabMetadata): string;
|
|
192
220
|
protected trackWidgetDefinition(index: number, widget: WidgetDefinition): string;
|
|
@@ -200,7 +228,7 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
200
228
|
protected styleCss(): string | null;
|
|
201
229
|
private cloneWidgetDefinition;
|
|
202
230
|
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisTabs, never>;
|
|
203
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTabs, "praxis-tabs", never, { "config": { "alias": "config"; "required": false; }; "tabsId": { "alias": "tabsId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "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>;
|
|
231
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTabs, "praxis-tabs", never, { "config": { "alias": "config"; "required": false; }; "tabsId": { "alias": "tabsId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "selectedIndex": { "alias": "selectedIndex"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "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>;
|
|
204
232
|
}
|
|
205
233
|
|
|
206
234
|
declare const PRAXIS_TABS_I18N_NAMESPACE = "praxisTabs";
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/tabs",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.12",
|
|
4
4
|
"description": "Configurable tabs (group and nav) for Praxis UI with metadata-driven content and runtime editor.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^20.0.0",
|
|
7
7
|
"@angular/core": "^20.0.0",
|
|
8
8
|
"@angular/material": "^20.0.0",
|
|
9
9
|
"@angular/cdk": "^20.0.0",
|
|
10
|
-
"@praxisui/core": "^8.0.0-beta.
|
|
11
|
-
"@praxisui/dynamic-fields": "^8.0.0-beta.
|
|
12
|
-
"@praxisui/settings-panel": "^8.0.0-beta.
|
|
10
|
+
"@praxisui/core": "^8.0.0-beta.12",
|
|
11
|
+
"@praxisui/dynamic-fields": "^8.0.0-beta.12",
|
|
12
|
+
"@praxisui/settings-panel": "^8.0.0-beta.12"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"tslib": "^2.3.0",
|