@praxisui/tabs 9.0.0-beta.1 → 9.0.0-beta.2
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 +73 -242
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Tabs"
|
|
3
3
|
slug: "tabs-overview"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Public npm documentation for @praxisui/tabs: group/nav modes, metadata-driven content, controlled selected index, persistence and runtime authoring."
|
|
5
5
|
doc_type: "reference"
|
|
6
6
|
document_kind: "component-overview"
|
|
7
7
|
component: "tabs"
|
|
@@ -24,7 +24,7 @@ icon: "tabs"
|
|
|
24
24
|
toc: true
|
|
25
25
|
sidebar: true
|
|
26
26
|
search_boost: 1.0
|
|
27
|
-
reading_time:
|
|
27
|
+
reading_time: 5
|
|
28
28
|
estimated_setup_time: 20
|
|
29
29
|
version: "1.0"
|
|
30
30
|
related_docs:
|
|
@@ -35,291 +35,122 @@ keywords:
|
|
|
35
35
|
- "mat-tab-group"
|
|
36
36
|
- "tab nav"
|
|
37
37
|
- "tabsId persistence"
|
|
38
|
-
last_updated: "2026-
|
|
38
|
+
last_updated: "2026-06-16"
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
# @praxisui/tabs
|
|
41
|
+
# @praxisui/tabs
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
`@praxisui/tabs` renders configurable group tabs and navigation tabs for Praxis UI Angular applications. Install it when a host needs metadata-driven tab composition, nested widgets, runtime editing, persisted configuration and controlled navigation state.
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
- Aplicação de referência: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
47
|
-
- Demo publicado: https://praxis-ui-4e602.web.app
|
|
48
|
-
- Indicado para: navegacao por abas metadata-driven com persistencia, widgets internos e editor em runtime
|
|
45
|
+
Use this package for UI composition. The host still owns route-level state, domain persistence, widget data providers and authorization.
|
|
49
46
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
- Organizar conteudo em grupos ou navegacao por abas com metadados
|
|
53
|
-
- Persistir configuracao e comportamento por instancia de tabs
|
|
54
|
-
- Compor tabs com widgets e campos dinamicos sem implementar cada variacao manualmente
|
|
55
|
-
|
|
56
|
-
Componente de abas (grupo e nav) configurável por metadados, com suporte a widgets internos, presets de estilo e editor integrado via Settings Panel.
|
|
57
|
-
|
|
58
|
-
## Instalação
|
|
47
|
+
## Install
|
|
59
48
|
|
|
60
49
|
```bash
|
|
61
50
|
npm i @praxisui/tabs@latest
|
|
62
51
|
```
|
|
63
52
|
|
|
64
53
|
Peer dependencies:
|
|
65
|
-
|
|
66
|
-
- `@angular/common` `^21.0.0`
|
|
67
|
-
- `@
|
|
68
|
-
- `@angular/router` `^21.0.0`
|
|
69
|
-
- `@angular/cdk` `^21.0.0`
|
|
70
|
-
- `@angular/material` `^21.0.0`
|
|
71
|
-
- `@praxisui/core` `^9.0.0-beta.1`
|
|
72
|
-
- `@praxisui/dynamic-fields` `^9.0.0-beta.1`
|
|
73
|
-
- `@praxisui/settings-panel` `^9.0.0-beta.1`
|
|
74
|
-
- `@praxisui/ai` `^9.0.0-beta.1`
|
|
54
|
+
|
|
55
|
+
- `@angular/common`, `@angular/core`, `@angular/forms`, `@angular/router`, `@angular/cdk`, `@angular/material` `^21.0.0`
|
|
56
|
+
- `@praxisui/core`, `@praxisui/dynamic-fields`, `@praxisui/settings-panel`, `@praxisui/ai` `^9.0.0-beta.1`
|
|
75
57
|
- `rxjs` `~7.8.0`
|
|
76
58
|
|
|
77
|
-
|
|
59
|
+
Runtime dependency included by the package:
|
|
60
|
+
|
|
61
|
+
- `immer` `^10.1.1`
|
|
62
|
+
|
|
63
|
+
## Minimal Standalone Tabs
|
|
78
64
|
|
|
79
65
|
```ts
|
|
80
66
|
import { Component } from '@angular/core';
|
|
81
|
-
import { PraxisTabs } from '@praxisui/tabs';
|
|
67
|
+
import { PraxisTabs, type TabsMetadata } from '@praxisui/tabs';
|
|
82
68
|
|
|
83
69
|
@Component({
|
|
84
70
|
selector: 'app-tabs-host',
|
|
85
71
|
standalone: true,
|
|
86
72
|
imports: [PraxisTabs],
|
|
87
|
-
template:
|
|
73
|
+
template: `
|
|
74
|
+
<praxis-tabs
|
|
75
|
+
tabsId="profile-tabs"
|
|
76
|
+
[config]="config"
|
|
77
|
+
[selectedIndex]="selectedIndex"
|
|
78
|
+
(selectedIndexChange)="selectedIndex = $event"
|
|
79
|
+
/>
|
|
80
|
+
`,
|
|
88
81
|
})
|
|
89
82
|
export class TabsHostComponent {
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
selectedIndex = 0;
|
|
84
|
+
|
|
85
|
+
readonly config: TabsMetadata = {
|
|
86
|
+
group: { selectedIndex: 0, stretchTabs: true },
|
|
92
87
|
tabs: [
|
|
93
|
-
{ id: 'summary',
|
|
94
|
-
{ id: 'history',
|
|
88
|
+
{ id: 'summary', textLabel: 'Summary' },
|
|
89
|
+
{ id: 'history', textLabel: 'History' },
|
|
95
90
|
],
|
|
96
91
|
};
|
|
97
92
|
}
|
|
98
93
|
```
|
|
99
94
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
- Dois modos de renderização: `group` (mat-tab-group) e `nav` (mat-tab-nav-bar).
|
|
103
|
-
- Suporte a conteúdo dinâmico por campo (`DynamicFieldLoader`) e por widget (`DynamicWidgetLoader`).
|
|
104
|
-
- Integração com Settings Panel para edição/configuração em tempo de execução.
|
|
105
|
-
- Persistência de configuração por `tabsId` usando `AsyncConfigStorage` (chave derivada via component_id).
|
|
106
|
-
- Lazy load opcional do conteúdo para melhor desempenho.
|
|
107
|
-
- Eventos reemitidos com contexto (para conexões entre widgets/páginas).
|
|
108
|
-
- Acessibilidade explícita por modo: `group.*` e `tabs[]` no modo group, `nav.*` no modo nav.
|
|
109
|
-
|
|
110
|
-
## API do Componente
|
|
111
|
-
|
|
112
|
-
Selector
|
|
113
|
-
- `praxis-tabs`
|
|
114
|
-
|
|
115
|
-
Inputs
|
|
116
|
-
- `config: TabsMetadata | null` Metadados completos para aparência, comportamento e conteúdo.
|
|
117
|
-
- `tabsId: string` Identificador estável para persistir/restaurar a configuração.
|
|
118
|
-
- `componentInstanceId?: string` Opcional para desambiguar múltiplas instâncias com o mesmo `tabsId` na mesma rota.
|
|
119
|
-
- `form?: FormGroup` FormGroup opcional para campos dinâmicos declarados em `content`.
|
|
120
|
-
- `context?: any` Contexto propagado a widgets internos (via `DynamicWidgetLoader`).
|
|
121
|
-
- `selectedIndex?: number` Índice ativo controlado por composição; não reemite `selectedIndexChange`.
|
|
122
|
-
- `enableCustomization?: boolean` Exibe botão de edição quando verdadeiro (abre o editor).
|
|
123
|
-
|
|
124
|
-
Outputs
|
|
125
|
-
- `selectedIndexChange: number` Índice selecionado atualizado (ambos modos).
|
|
126
|
-
- `selectedTabChange: MatTabChangeEvent` Evento nativo do MatTabGroup.
|
|
127
|
-
- `focusChange, animationDone, indexFocused, selectFocusedIndex` Eventos nativos do Angular Material.
|
|
128
|
-
- `configChange: TabsConfigChangeEvent` Emite `inputPatch.config` quando autoria assistida altera `TabsMetadata`, permitindo que hosts persistam a nova configuração no manifesto/página canônica.
|
|
129
|
-
- `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`.
|
|
130
|
-
|
|
131
|
-
## Uso Controlado por Composição
|
|
132
|
-
|
|
133
|
-
`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`.
|
|
134
|
-
|
|
135
|
-
Padrão recomendado para páginas dinâmicas:
|
|
136
|
-
|
|
137
|
-
- grave a seleção do usuário com `selectedIndexChange -> state`;
|
|
138
|
-
- projete o estado de volta com `state -> selectedIndex`;
|
|
139
|
-
- declare `selectedIndex` depois de `config` em `bindingOrder`, para que a configuração seja carregada antes da seleção controlada;
|
|
140
|
-
- não persista `inputs.selectedIndex` estático em recipes quando a seleção vem de `composition.links`.
|
|
141
|
-
|
|
142
|
-
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`.
|
|
143
|
-
|
|
144
|
-
Exemplo canônico:
|
|
145
|
-
|
|
146
|
-
```json
|
|
147
|
-
{
|
|
148
|
-
"links": [
|
|
149
|
-
{
|
|
150
|
-
"id": "tabs.selectedIndexChange->state.navigation.activeTabIndex",
|
|
151
|
-
"from": { "kind": "component-port", "ref": { "widget": "workspaceTabs", "port": "selectedIndexChange" } },
|
|
152
|
-
"to": { "kind": "state", "ref": { "path": "navigation.activeTabIndex", "layer": "values", "write": true } }
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
"id": "state.navigation.activeTabIndex->tabs.selectedIndex",
|
|
156
|
-
"from": { "kind": "state", "ref": { "path": "navigation.activeTabIndex", "layer": "values" } },
|
|
157
|
-
"to": { "kind": "component-port", "ref": { "widget": "workspaceTabs", "port": "selectedIndex" } }
|
|
158
|
-
}
|
|
159
|
-
]
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Persistência
|
|
164
|
-
- Quando `tabsId` é fornecido, a configuração é salva/recuperada em `AsyncConfigStorage` na chave `tabs:<component_id>`.
|
|
165
|
-
- O `component_id` é derivado via `ComponentKeyService` (inclui rota, tipo de componente, `tabsId` e `componentInstanceId` quando informado).
|
|
166
|
-
|
|
167
|
-
## Empty State e Quick Setup
|
|
95
|
+
## Main Inputs And Outputs
|
|
168
96
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
```ts
|
|
180
|
-
export interface TabsMetadata {
|
|
181
|
-
appearance?: {
|
|
182
|
-
density?: 'compact' | 'comfortable' | 'spacious';
|
|
183
|
-
themeClass?: string;
|
|
184
|
-
customCss?: string; // CSS injetado inline
|
|
185
|
-
tokens?: Partial<TabsStyleTokens>; // tokens -> CSS gerado em runtime
|
|
186
|
-
};
|
|
187
|
-
behavior?: { lazyLoad?: boolean; closeable?: boolean; reorderable?: boolean };
|
|
188
|
-
accessibility?: { highContrast?: boolean; reduceMotion?: boolean };
|
|
189
|
-
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; };
|
|
190
|
-
tabs?: Array<{ id?: string; textLabel?: string; icon?: string; disabled?: boolean; visible?: boolean; labelClass?: string|string[]; bodyClass?: string|string[]; content?: any[]; widgets?: WidgetDefinition[] }>;
|
|
191
|
-
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 };
|
|
192
|
-
}
|
|
193
|
-
```
|
|
97
|
+
- `config: TabsMetadata | null`: canonical tabs/nav configuration.
|
|
98
|
+
- `tabsId: string`: stable id used for local configuration persistence.
|
|
99
|
+
- `componentInstanceId?: string`: disambiguates multiple instances with the same `tabsId`.
|
|
100
|
+
- `form?: FormGroup`: form context for dynamic field content.
|
|
101
|
+
- `context?: unknown`: context passed to nested widgets.
|
|
102
|
+
- `selectedIndex?: number`: controlled active tab index.
|
|
103
|
+
- `enableCustomization?: boolean`: shows runtime editing affordances.
|
|
104
|
+
- `selectedIndexChange`: emits user tab changes.
|
|
105
|
+
- `configChange`: emits host-persistable config patches after runtime authoring.
|
|
106
|
+
- `widgetEvent`: legacy/advanced bridge for nested widget events; prefer composition links for new integrations.
|
|
194
107
|
|
|
195
|
-
|
|
196
|
-
- Exemplos: `active-indicator-color`, `active-label-text-color`, `inactive-label-text-color`, `pagination-icon-color`, `divider-color`, `background-color`.
|
|
197
|
-
- São transformados em CSS scoped por `data-tabs-id` em tempo de execução.
|
|
108
|
+
Controlled `selectedIndex` updates the active tab without re-emitting `selectedIndexChange`, which prevents loops in dynamic-page state projections.
|
|
198
109
|
|
|
199
|
-
##
|
|
110
|
+
## Metadata Shape
|
|
200
111
|
|
|
201
|
-
|
|
112
|
+
`TabsMetadata` supports two primary modes:
|
|
202
113
|
|
|
203
114
|
```ts
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
Contrato do Editor (`PraxisTabsConfigEditor` implementa `SettingsValueProvider`):
|
|
214
|
-
- `isDirty$`, `isValid$`, `isBusy$` controlam a habilitação dos botões.
|
|
215
|
-
- `getSettingsValue()` e `onSave()` retornam `{ config: TabsMetadata }`.
|
|
216
|
-
- Abas do editor: Comportamento, Grupo, Nav, JSON, Estilo, Abas, Links.
|
|
217
|
-
- JSON: editor de texto com validação e botão “Formatar”.
|
|
218
|
-
- Estilo: presets de tokens, classe de tema, CSS customizado e snippet SCSS sugerido.
|
|
219
|
-
- Abas/Links: adicionar/remover/reordenar, inserir widgets, presets rápidos (form/table/crud) usando `resourcePath`.
|
|
220
|
-
- O editor cobre apenas caminhos com binding real no runtime; campos sem efeito não são expostos na UI.
|
|
221
|
-
|
|
222
|
-
Quick Setup
|
|
223
|
-
- `openQuickSetup()` abre `TabsQuickSetupComponent` para criação rápida de abas/links.
|
|
224
|
-
- `applied$`/`saved$` aplicam a configuração ao componente.
|
|
225
|
-
|
|
226
|
-
## Agentic Authoring
|
|
227
|
-
|
|
228
|
-
`@praxisui/tabs` publica `PRAXIS_TABS_AUTHORING_MANIFEST` para orientar edições assistidas por IA sobre `TabsMetadata`.
|
|
229
|
-
|
|
230
|
-
- **Editable targets:** `tab`, `tabLabel`, `tabIcon`, `tabContent`, `activeTab`, `visibility`, `disabledState` e `layout`.
|
|
231
|
-
- **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`.
|
|
232
|
-
- **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.
|
|
233
|
-
- **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.
|
|
234
|
-
- **Current-area authoring:** pedidos como “nesta aba”, “aba atual” ou “dentro da aba” devem materializar `tab.content.set` no item ativo/resolvido, não `tab.add`; criar nova aba exige intenção explícita como “nova aba” ou “adicionar aba”.
|
|
235
|
-
- **Registry projection:** o manifesto é exportado no `public-api` e projetado em `components['praxis-tabs'].authoringManifest` pelo AI Registry.
|
|
236
|
-
|
|
237
|
-
### Praxis Semantic Assistant
|
|
238
|
-
|
|
239
|
-
When `enableCustomization=true`, `praxis-tabs` opens the shared `PraxisAiAssistantShellComponent` and registers a minimized global session instead of embedding the legacy `PraxisAiAssistantComponent`.
|
|
240
|
-
|
|
241
|
-
- The assistant context is safe and semantic: component identity, tabs id, current mode, tab/link counts, field-name digest, manifest reference and governance hints.
|
|
242
|
-
- Business-rule, policy, compliance, publication, materialization or enforcement prompts are routed to governed `domain-rules/intake` handoff and are not applied as local tabs configuration.
|
|
243
|
-
- Free JSON patches from the backend are rejected. Local apply remains blocked until the response is compiled from a manifest-backed `componentEditPlan` validated against `PRAXIS_TABS_AUTHORING_MANIFEST`.
|
|
244
|
-
- `TabsAiAdapter.applyPatch(...)` remains available for legacy/editor internals, but the new assistant turn flow does not use it as an ungoverned patch path.
|
|
245
|
-
|
|
246
|
-
## Eventos e Conexões
|
|
247
|
-
|
|
248
|
-
Para conexoes canonicas de widgets internos, use `composition.links` com endpoint `component-port + nestedPath`.
|
|
249
|
-
|
|
250
|
-
Exemplo de output de uma lista dentro da primeira tab:
|
|
115
|
+
const groupTabs: TabsMetadata = {
|
|
116
|
+
behavior: { lazyLoad: true },
|
|
117
|
+
group: { selectedIndex: 0, dynamicHeight: true },
|
|
118
|
+
tabs: [
|
|
119
|
+
{ id: 'general', textLabel: 'General' },
|
|
120
|
+
{ id: 'orders', textLabel: 'Orders', widgets: [{ id: 'praxis-table' }] },
|
|
121
|
+
],
|
|
122
|
+
};
|
|
251
123
|
|
|
252
|
-
|
|
253
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{ "kind": "tab", "id": "employees-list", "index": 0 },
|
|
259
|
-
{ "kind": "widget", "key": "employees-list", "componentType": "praxis-list" }
|
|
124
|
+
const navTabs: TabsMetadata = {
|
|
125
|
+
nav: {
|
|
126
|
+
selectedIndex: 0,
|
|
127
|
+
links: [
|
|
128
|
+
{ id: 'overview', label: 'Overview' },
|
|
129
|
+
{ id: 'settings', label: 'Settings' },
|
|
260
130
|
],
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
}
|
|
131
|
+
},
|
|
132
|
+
};
|
|
265
133
|
```
|
|
266
134
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
- `ref.widget` e a instancia top-level de `praxis-tabs`;
|
|
270
|
-
- `nestedPath` e relativo a essa instancia e deve terminar em `kind: "widget"` com `key` estavel;
|
|
271
|
-
- `ref.port` e a porta real do widget filho;
|
|
272
|
-
- inputs para filhos nested devem atualizar a configuracao declarativa do filho, nao depender de dot-path publico sobre `config`.
|
|
273
|
-
|
|
274
|
-
`widgetEvent` continua existindo como bridge avancada/legado para transporte de eventos internos com contexto da origem:
|
|
275
|
-
|
|
276
|
-
- Forma do evento: `{ tabId?, tabIndex?, linkId?, linkIndex?, sourceId, output?, payload }`.
|
|
277
|
-
- Nao use `widgetEvent` como caminho principal para authoring novo de nested ports.
|
|
278
|
-
- Nao use dot-path de `config.tabs[].widgets[]` como contrato publico para novos links nested.
|
|
279
|
-
|
|
280
|
-
## Lazy Load
|
|
281
|
-
|
|
282
|
-
- Ative `behavior.lazyLoad = true` para renderizar conteúdo somente quando a aba/link é visitado.
|
|
283
|
-
- O componente gerencia caches de índices visitados para não re-renderizar desnecessariamente.
|
|
135
|
+
Use stable ids for tabs and nav links. When `tabsId` is provided, the component stores configuration under a key derived from route, component type, `tabsId` and optional `componentInstanceId`.
|
|
284
136
|
|
|
285
|
-
##
|
|
137
|
+
## Runtime Authoring
|
|
286
138
|
|
|
287
|
-
|
|
288
|
-
<praxis-tabs [config]="tabsCfg" [tabsId]="'cliente-tabs'" [enableCustomization]="true"></praxis-tabs>
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
```ts
|
|
292
|
-
// tabsCfg simples (modo grupo)
|
|
293
|
-
const tabsCfg: TabsMetadata = {
|
|
294
|
-
group: { selectedIndex: 0 },
|
|
295
|
-
tabs: [
|
|
296
|
-
{ id: 't1', textLabel: 'Geral', widgets: [{ id: 'praxis-dynamic-form', inputs: { resourcePath: 'clientes' } }] },
|
|
297
|
-
{ id: 't2', textLabel: 'Pedidos', widgets: [{ id: 'praxis-table', inputs: { resourcePath: 'pedidos' } }] },
|
|
298
|
-
],
|
|
299
|
-
};
|
|
300
|
-
```
|
|
139
|
+
With `enableCustomization`, the component can open quick setup or the full `PraxisTabsConfigEditor` through Settings Panel. The editor round-trips through `TabsAuthoringDocument`, applies only runtime-backed fields and emits `configChange` so the host can persist canonical page or manifest changes.
|
|
301
140
|
|
|
302
|
-
|
|
303
|
-
- `praxis-table` se auto-hospeda para `GenericCrudService`.
|
|
304
|
-
- `praxis-dynamic-form` remoto continua dependendo de `GenericCrudService` provido pelo host efetivo quando usar `resourcePath`, `resourceId`, schema remoto ou submit remoto.
|
|
305
|
-
- ao embutir `praxis-dynamic-form` em tabs, stepper ou shells equivalentes, nao presumir que o widget sozinho resolve a DI de CRUD.
|
|
141
|
+
`PRAXIS_TABS_AUTHORING_MANIFEST` describes the governed AI/tooling operations for tab add/remove, labels, icons, order, visibility, disabled state, active tab, layout and tab content. Free JSON patches from AI flows are not the public authoring contract.
|
|
306
142
|
|
|
307
|
-
##
|
|
143
|
+
## Accessibility
|
|
308
144
|
|
|
309
|
-
|
|
310
|
-
- Modo `nav`: use `nav.ariaLabel` e `nav.ariaLabelledby`.
|
|
311
|
-
- Opções top-level de acessibilidade com binding real: `accessibility.reduceMotion` e `accessibility.highContrast`.
|
|
145
|
+
For group mode, set `group.ariaLabel`, `group.ariaLabelledby`, `tabs[].ariaLabel` or `tabs[].ariaLabelledby` where needed. For nav mode, set `nav.ariaLabel` or `nav.ariaLabelledby`. `accessibility.reduceMotion` and `accessibility.highContrast` are the supported top-level accessibility flags.
|
|
312
146
|
|
|
313
|
-
##
|
|
147
|
+
## Public API Snapshot
|
|
314
148
|
|
|
315
|
-
|
|
316
|
-
- Tokens de estilo aceitam CSS vars ou cores (`#RRGGBB`/`rgb(...)`).
|
|
317
|
-
- Em M2, `color` e `backgroundColor` seguem as opções do Angular Material; em M3, prefira tokens.
|
|
318
|
-
- A classe de tema é decisão do host (`.dark-theme` ou `.theme-dark`/`.theme-light`); mantenha tokens e componentes no mesmo escopo.
|
|
319
|
-
- `group.contentTabIndex`, `accessibility.ariaLabels` e `accessibility.keyboardNavigation` permanecem fora da superfície pública suportada enquanto não houver binding explícito no DOM.
|
|
149
|
+
Main exports include `PraxisTabs`, `TabsMetadata`, i18n helpers, runtime metadata, `PraxisTabsConfigEditor`, `PraxisTabsWidgetConfigEditor`, tabs authoring document helpers, AI capabilities and `PRAXIS_TABS_AUTHORING_MANIFEST`.
|
|
320
150
|
|
|
321
|
-
|
|
151
|
+
## Official Links
|
|
322
152
|
|
|
323
|
-
-
|
|
324
|
-
-
|
|
325
|
-
-
|
|
153
|
+
- Documentation: https://praxisui.dev/components/tabs
|
|
154
|
+
- Live demo: https://praxis-ui-4e602.web.app
|
|
155
|
+
- Quickstart repository: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
156
|
+
- Source and issues: https://github.com/codexrodrigues/praxis-ui-angular
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/tabs",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.2",
|
|
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": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
8
|
"@angular/material": "^21.0.0",
|
|
9
9
|
"@angular/cdk": "^21.0.0",
|
|
10
|
-
"@praxisui/core": "^9.0.0-beta.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.0-beta.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.0-beta.
|
|
10
|
+
"@praxisui/core": "^9.0.0-beta.2",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.0-beta.2",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.0-beta.2",
|
|
13
13
|
"@angular/forms": "^21.0.0",
|
|
14
14
|
"@angular/router": "^21.0.0",
|
|
15
|
-
"@praxisui/ai": "^9.0.0-beta.
|
|
15
|
+
"@praxisui/ai": "^9.0.0-beta.2",
|
|
16
16
|
"rxjs": "~7.8.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/codexrodrigues/praxis-ui-angular"
|
|
28
|
+
"url": "git+https://github.com/codexrodrigues/praxis-ui-angular.git"
|
|
29
29
|
},
|
|
30
30
|
"homepage": "https://praxisui.dev",
|
|
31
31
|
"bugs": {
|