@praxisui/tabs 8.0.0-beta.2 → 8.0.0-beta.21

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.
@@ -0,0 +1,978 @@
1
+ ---
2
+ title: "praxis-tabs JSON API (Canonical)"
3
+ slug: "praxis-tabs-json-api"
4
+ doc_type: "api-reference"
5
+ component: "praxis-tabs"
6
+ document_kind: "json-api-canonical"
7
+ reference_mode: "canonical"
8
+ contract_format: "json"
9
+ contract_source: "runtime-and-code"
10
+ description: "Referencia canonica do contrato JSON do componente praxis-tabs."
11
+ category: "components"
12
+ sub_category: "tabs"
13
+ audience:
14
+ - "frontend"
15
+ - "architect"
16
+ - "platform-team"
17
+ level: "advanced"
18
+ status: "active"
19
+ owner: "praxis-ui"
20
+ source_of_truth:
21
+ - "projects/praxis-tabs/src/lib/praxis-tabs.ts"
22
+ - "projects/praxis-tabs/src/lib/praxis-tabs.spec.ts"
23
+ - "projects/praxis-tabs/src/lib/praxis-tabs-widget-event.spec.ts"
24
+ - "projects/praxis-tabs/src/lib/praxis-tabs.metadata.ts"
25
+ - "projects/praxis-tabs/src/lib/praxis-tabs-config-editor.ts"
26
+ - "projects/praxis-tabs/src/lib/quick-setup/tabs-quick-setup.component.ts"
27
+ - "projects/praxis-tabs/src/lib/ai/tabs-ai.adapter.ts"
28
+ - "projects/praxis-tabs/src/lib/ai/tabs-ai-capabilities.ts"
29
+ - "projects/praxis-tabs/src/lib/ai/tabs-context-pack.ts"
30
+ source_of_truth_last_verified: "2026-03-05"
31
+ last_updated: "2026-03-05"
32
+ toc: true
33
+ sidebar: true
34
+ tags:
35
+ - "json-api"
36
+ - "canonical-contract"
37
+ - "praxis-tabs"
38
+ api_stability: "canonical"
39
+ schema_verified: true
40
+ runtime_verified: false
41
+ editor_coverage_verified: false
42
+ runtime_scope: "public"
43
+ legacy_paths_present: false
44
+ has_known_mismatches: true
45
+ related_components: []
46
+ ---
47
+
48
+ # praxis-tabs
49
+
50
+ Este documento e a referencia canonica da API JSON de praxis-tabs.
51
+
52
+ ## Summary
53
+
54
+ - Tipo documental: API reference canonica de contrato JSON.
55
+ - Source of truth: runtime e codigo declarados no frontmatter.
56
+ - Objetivo operacional: consulta rapida, auditavel e deterministica sob pressao.
57
+ - Resumo funcional herdado: `praxis-tabs` e um runtime declarativo de navegacao por abas orientado a metadata: voce descreve estrutura, comportamento e conteudo em JSON (`TabsMetadata`) e o motor renderiza a UI com padrao corporativo (persistencia, lazy loading, reorder, widgets e editor em runtime). Nao e apenas um wrapper de `mat-tab-group`: e um host config-first para escalar UIs dinamicas com governanca.
58
+
59
+ ## Scope and positioning
60
+
61
+ - Escopo: contrato JSON publico e limites de comportamento observavel.
62
+ - Fora de escopo: tutorial de adocao e walkthrough operacional detalhado.
63
+ - Posicionamento: referencia canonicamente governada para consumidores, arquitetos e mantenedores.
64
+
65
+ ## Source of truth
66
+
67
+ | Source | Kind | Notes |
68
+ | --- | --- | --- |
69
+ | projects/praxis-tabs/src/lib/praxis-tabs.ts | runtime-code | Source de implementacao declarado no repositorio. |
70
+ | projects/praxis-tabs/src/lib/praxis-tabs.spec.ts | runtime-code | Source de implementacao declarado no repositorio. |
71
+ | projects/praxis-tabs/src/lib/praxis-tabs-widget-event.spec.ts | runtime-code | Source de implementacao declarado no repositorio. |
72
+ | projects/praxis-tabs/src/lib/praxis-tabs.metadata.ts | runtime-code | Source de implementacao declarado no repositorio. |
73
+ | projects/praxis-tabs/src/lib/praxis-tabs-config-editor.ts | runtime-code | Source de implementacao declarado no repositorio. |
74
+ | projects/praxis-tabs/src/lib/quick-setup/tabs-quick-setup.component.ts | runtime-code | Source de implementacao declarado no repositorio. |
75
+ | projects/praxis-tabs/src/lib/ai/tabs-ai.adapter.ts | runtime-code | Source de implementacao declarado no repositorio. |
76
+ | projects/praxis-tabs/src/lib/ai/tabs-ai-capabilities.ts | runtime-code | Source de implementacao declarado no repositorio. |
77
+ | projects/praxis-tabs/src/lib/ai/tabs-context-pack.ts | runtime-code | Source de implementacao declarado no repositorio. |
78
+
79
+ ## Support legend
80
+
81
+ - Active: suportado e observado no runtime atual.
82
+ - Partial: suporte parcial, com restricoes conhecidas.
83
+ - Declared-only: declarado em tipos/schema sem ligacao runtime confirmada.
84
+ - Schema-only: presente em schema/modelo sem confirmacao de execucao.
85
+ - Deprecated: mantido por compatibilidade legada com migracao prevista.
86
+
87
+ ## Contract classification
88
+
89
+ ### Canonical paths (public contract)
90
+
91
+ | Path | Type | Required | Default | Status | Notes |
92
+ | --- | --- | --- | --- | --- | --- |
93
+ | `group.alignTabs` | not-specified | not-specified | n/a | Active | `mat-align-tabs` |
94
+ | `group.animationDuration` | not-specified | not-specified | n/a | Active | `effectiveAnimationDuration()` |
95
+ | `group.ariaLabel` | not-specified | not-specified | n/a | Active | atributo no `mat-tab-group` |
96
+ | `group.ariaLabelledby` | not-specified | not-specified | n/a | Active | atributo no `mat-tab-group` |
97
+ | `group.color` | not-specified | not-specified | n/a | Active | prop Material M2 |
98
+ | `group.backgroundColor` | not-specified | not-specified | n/a | Active | prop Material M2 |
99
+ | `group.contentTabIndex` | not-specified | not-specified | n/a | Declared-only | sem binding no template; manter fora do contrato público |
100
+ | `group.disablePagination` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
101
+ | `group.disableRipple` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
102
+ | `group.dynamicHeight` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
103
+ | `group.fitInkBarToContent` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
104
+ | `group.headerPosition` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
105
+ | `group.preserveContent` | not-specified | not-specified | n/a | Active | prop `mat-tab-group` |
106
+ | `group.selectedIndex` | not-specified | not-specified | n/a | Active | estado interno + persistencia + clamp |
107
+
108
+ ### Supported legacy paths
109
+
110
+ Nenhum path legado suportado foi identificado nesta revisão baseada em evidência textual preservada.
111
+
112
+ ### Internal-only paths
113
+
114
+ | Path | Internal consumer | Runtime presence | Public support | Notes |
115
+ | --- | --- | --- | --- | --- |
116
+ | `tabs:{componentKey}` | persistência interna (`ASYNC_CONFIG_STORAGE`) | Yes | No | Namespace interno para salvar/restaurar `TabsMetadata`. |
117
+ | `groupLoaded/navLoaded` | lazy-load cache interno | Yes | No | Estado transitório de render de abas/links carregados. |
118
+
119
+ ### Experimental paths
120
+
121
+ | Path | Enablement (flag/guard) | Stability | Rollout notes | Notes |
122
+ | --- | --- | --- | --- | --- |
123
+ | `behavior.lazyLoad` | flag no contrato + caches internos | Partial | Cobrir casos de reorder/close com regressão visual | Ativo no runtime com política de cache por índice. |
124
+
125
+ ## Overview
126
+
127
+ Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecnico existente. O conteudo detalhado anterior foi preservado para manter rastreabilidade historica e reduzir perda de contexto.
128
+
129
+ ## Public contract surface
130
+
131
+ ### Top-level configuration blocks
132
+
133
+ | Block | Purpose | Required | Merge strategy | Notes |
134
+ | --- | --- | --- | --- | --- |
135
+ | `appearance` | Densidade, tema e tokens visuais | No | deep-merge | Aplica classes/tokens em runtime por instância. |
136
+ | `behavior` | Lazy load, closeable e reorderable | No | deep-merge | Controla interação e ciclo de conteúdo por aba/link. |
137
+ | `accessibility` | A11y e redução de movimento | No | deep-merge | `reduceMotion` altera duração efetiva de animação. |
138
+ | `group` | Configuração do `mat-tab-group` | No | deep-merge | Inclui seleção inicial e props de navegação Material. |
139
+ | `tabs[]` | Definição de abas (modo group) | No | replace-array | Conteúdo/widgts por aba e metadados de label. |
140
+ | `nav` | Definição de links (modo nav) | No | deep-merge | Alternativa ao modo group com links configuráveis. |
141
+
142
+ ### Nested configuration blocks
143
+
144
+ | Path | Type | Required | Default | Constraints | Notes |
145
+ | --- | --- | --- | --- | --- | --- |
146
+ | `group.alignTabs` | not-specified | not-specified | n/a | component-defined | `mat-align-tabs` |
147
+ | `group.animationDuration` | not-specified | not-specified | n/a | component-defined | `effectiveAnimationDuration()` |
148
+ | `group.ariaLabel` | not-specified | not-specified | n/a | component-defined | atributo no `mat-tab-group` |
149
+ | `group.ariaLabelledby` | not-specified | not-specified | n/a | component-defined | atributo no `mat-tab-group` |
150
+ | `group.color` | not-specified | not-specified | n/a | component-defined | prop Material M2 |
151
+ | `group.backgroundColor` | not-specified | not-specified | n/a | component-defined | prop Material M2 |
152
+ | `group.contentTabIndex` | not-specified | not-specified | n/a | Declared-only | sem binding no template; tipado apenas para compatibilidade transitória |
153
+ | `group.disablePagination` | not-specified | not-specified | n/a | component-defined | prop `mat-tab-group` |
154
+ | `group.disableRipple` | not-specified | not-specified | n/a | component-defined | prop `mat-tab-group` |
155
+ | `group.dynamicHeight` | not-specified | not-specified | n/a | component-defined | prop `mat-tab-group` |
156
+
157
+ ### Input bindings
158
+
159
+ | Binding/Path | Type | Required | Source | Runtime normalization | Notes |
160
+ | --- | --- | --- | --- | --- | --- |
161
+ | `config` | `TabsMetadata \| null` | No | component-input/storage | `syncSelectionFromConfig()` + clamp | Contrato principal da navegação por abas. |
162
+ | `tabsId` | `string` | Yes (logical) | component-input | component key builder | Necessário para escopo de persistência. |
163
+ | `componentInstanceId` | `string \| undefined` | No | component-input | component key scoping | Isola armazenamento por instância. |
164
+ | `enableCustomization` | `boolean` | No | component-input | boolean coercion | Habilita operações de edição/quick setup. |
165
+ | `form` | `FormGroup \| null` | No | component-input | passthrough | Contexto de formulário para conteúdo dinâmico interno. |
166
+ | `context` | `Record<string, any> \| null` | No | component-input | passthrough | Contexto adicional repassado a widgets internos. |
167
+
168
+ ### Output events
169
+
170
+ | Event | Payload | Trigger | Stability | Notes |
171
+ | --- | --- | --- | --- | --- |
172
+ | `animationDone` | `void` | Final da animacao no `mat-tab-group` | Partial | Preservado da documentação anterior. |
173
+ | `focusChange` | `MatTabChangeEvent` | Mudanca de foco em aba (group) | Partial | Preservado da documentação anterior. |
174
+ | `selectedIndexChange` | `number` | Selecao em `onSelectedIndexChange` (group) e `onNavClick` (nav) | Partial | Preservado da documentação anterior. |
175
+ | `selectedTabChange` | `MatTabChangeEvent` | Troca de aba no `mat-tab-group` | Partial | Preservado da documentação anterior. |
176
+ | `indexFocused` | `number` | Evento nativo de foco indexado (Material) | Partial | Preservado da documentação anterior. |
177
+ | `selectFocusedIndex` | `number` | Evento nativo de selecao por foco (Material) | Partial | Preservado da documentação anterior. |
178
+ | `widgetEvent` | `{ tabId?, tabIndex?, linkId?, linkIndex?, sourceId, output?, payload? }` | Reemissao de evento vindo de widget interno com contexto de localizacao | Partial | Preservado da documentação anterior. |
179
+
180
+ ### External side channels
181
+
182
+ | Channel | Direction | Contract | Failure mode | Notes |
183
+ | --- | --- | --- | --- | --- |
184
+ | `ASYNC_CONFIG_STORAGE` | bidirectional | `loadConfig/saveConfig/clearConfig` | fail-open | Persistência de seleção e configuração das abas. |
185
+ | `SettingsPanelService` | bidirectional | `open(...).applied$/saved$` | fail-open | Editor runtime e quick setup sem recarregar host. |
186
+ | `MatSnackBar` | outbound notify | `open(message, ...)` | fail-soft | Feedback de reset de preferências. |
187
+
188
+ ### Host/runtime dependencies
189
+
190
+ | Dependency | Required | Environment | Purpose | Notes |
191
+ | --- | --- | --- | --- | --- |
192
+ | `ASYNC_CONFIG_STORAGE` | Yes | browser/dev/prod | persistência | Carrega/salva `TabsMetadata` por chave de componente. |
193
+ | `SettingsPanelService` | Yes | browser/dev/prod | editor runtime | Integra editor e quick setup de abas. |
194
+ | `ComponentKeyService` | Yes | browser/dev/prod/ssr | chave de escopo | Evita colisão de estado entre instâncias. |
195
+ | `MatTabsModule` | Yes | browser/dev/prod | render base | Runtime principal para modo group. |
196
+ | `DynamicWidgetLoaderDirective` | Optional per config | browser/dev/prod | widgets internos | Reemite eventos via `widgetEvent`. |
197
+ | `MatSnackBar` | Optional | browser/dev/prod | UX feedback | Avisos operacionais como reset de preferências. |
198
+
199
+ ## Coverage matrix
200
+
201
+ | Surface | Verified | Coverage status | Evidence | Notes |
202
+ | --- | --- | --- | --- | --- |
203
+ | Runtime | false | Partial | source_of_truth + conteudo preservado | Revisao estrutural concluida; validacao comportamental fina pode exigir follow-up. |
204
+ | Schema/Types | true | Partial | interfaces/modelos citados | Mapeamento formal de todos os campos ainda pode requerer refinamento. |
205
+ | Editor/Tooling | false | Partial | secoes de editor quando presentes | Cobertura de editor/tooling nem sempre confirmada por evidencia direta. |
206
+
207
+ ## Runtime coverage boundaries
208
+
209
+ - Cobertura consolidada com base em documentacao existente e source of truth declarado.
210
+ - Comportamentos fora de evidencia direta foram marcados como not-yet-verified ou Partial.
211
+ - Compatibilidade legada, quando detectada, foi separada em classificacao explicita.
212
+
213
+ ## Resolution model
214
+
215
+ ### Merge order
216
+
217
+ 1. contrato em `@Input() config` (quando fornecido)
218
+ 2. hidratação opcional de storage no `ngOnInit()`
219
+ 3. normalização de seleção via `syncSelectionFromConfig()`
220
+ 4. persistência incremental após mudanças (`persistConfig`)
221
+
222
+ ### Fallback order
223
+
224
+ config explícita -> config persistida -> seleção clamp para `0` quando índice inválido/ausente.
225
+
226
+ ### Override points
227
+
228
+ - `@Input() config`, `@Input() tabsId`, `@Input() componentInstanceId`
229
+ - editor runtime (`openEditor`, `openQuickSetup`)
230
+ - persistência por host (`ASYNC_CONFIG_STORAGE`)
231
+
232
+ ### Runtime normalization
233
+
234
+ - `clampIndex()` evita seleção fora de faixa após reorder/remove.
235
+ - `syncSelectionFromConfig()` reconcilia estado de seleção para modos group/nav.
236
+ - `effectiveAnimationDuration()` aplica `reduceMotion` como override de duração.
237
+
238
+ ### Precedence rules
239
+
240
+ - seleção runtime (`selectedIndexSignal/currentNavIndex`) é derivada de `config` e sempre clamped.
241
+ - eventos de editor `saved` e `applied` sobrescrevem config atual; `saved` também persiste.
242
+ - ausência de `tabsId` mantém componente funcional, mas sem persistência.
243
+
244
+ ## Validation and error semantics
245
+
246
+ ### Validation model
247
+
248
+ | Path/Rule | Validation phase | Behavior on fail | Error code / warning | Notes |
249
+ | --- | --- | --- | --- | --- |
250
+ | `tabsId` para persistência | init/runtime | warning + disable persistence | `praxis-tabs:missing-tabs-id` | Fluxo visual continua sem restore/save de estado. |
251
+ | índices de seleção (`group.selectedIndex`, `nav.selectedIndex`) | runtime | clamp para faixa válida | n/a | Previne acesso fora dos limites após mudanças dinâmicas. |
252
+ | payload de reorder/nav click inválido | runtime | ignore operation | n/a | Guardas de índice evitam mutações incorretas. |
253
+ | valores CSS inseguros em appearance | runtime sanitize | sanitize/ignore | n/a | `sanitizeCssValue()` limita superfícies de injeção de estilo. |
254
+
255
+ ### Error semantics
256
+
257
+ Predomina tratamento fail-open com guardas de índice e persistência opcional. Falhas em storage ou operações inválidas não derrubam renderização das abas.
258
+
259
+ ### Fail-open / fail-closed behavior
260
+
261
+ | Condition | Mode | Runtime behavior | Consumer impact |
262
+ | --- | --- | --- | --- |
263
+ | Falha em `loadConfig/saveConfig` | fail-open | mantém config em memória | sem perda de navegação atual |
264
+ | índice inválido após reorder/remove | fail-open | clamp para índice seguro | evita erro de render/navegação |
265
+ | operação de drag inválida | fail-open | ignora mutação | sem corrupção de estado |
266
+ | config ausente ou parcial | fail-soft | renderiza estado mínimo (sem abas/links) | componente permanece estável |
267
+
268
+ ### Invalid or unknown field handling
269
+
270
+ - Campos desconhecidos: comportamento depende da estrategia do componente (ignore, warn ou reject).
271
+ - Campos invalidos: podem gerar fallback, warning ou falha conforme implementacao.
272
+ - Registrar divergencias observadas em Known limitations and mismatches.
273
+
274
+ ### Runtime warnings vs hard failures
275
+
276
+ | Condition | Severity | Observability | Consumer action |
277
+ | --- | --- | --- | --- |
278
+ | partial-or-declared-only-coverage | warning | logs/eventos do componente | confirmar ligacao runtime antes de uso critico |
279
+
280
+ ## Detailed API
281
+
282
+ ### Preserved technical reference (normalized from previous revision)
283
+
284
+ `praxis-tabs` e um runtime declarativo de navegacao por abas orientado a metadata: voce descreve estrutura, comportamento e conteudo em JSON (`TabsMetadata`) e o motor renderiza a UI com padrao corporativo (persistencia, lazy loading, reorder, widgets e editor em runtime). Nao e apenas um wrapper de `mat-tab-group`: e um host config-first para escalar UIs dinamicas com governanca.
285
+
286
+ ### Prova em 20 segundos
287
+
288
+ Cole este JSON e renderize tabs funcionais sem reescrever template:
289
+
290
+ ```json
291
+ {
292
+ "behavior": { "lazyLoad": true },
293
+ "group": { "selectedIndex": 0, "stretchTabs": true },
294
+ "tabs": [
295
+ { "id": "dados", "textLabel": "Dados" },
296
+ { "id": "itens", "textLabel": "Itens" }
297
+ ]
298
+ }
299
+ ```
300
+
301
+ - Troque `textLabel` e a UI muda sem alterar o componente host.
302
+ - Ative `widgets` por aba e a composicao passa a ser metadata-driven.
303
+ - As regras de selecao e persistencia continuam previsiveis e versionaveis.
304
+
305
+ Ver demo/recipe no workspace de exemplos: `examples/ai-recipes/praxis-tabs.json`
306
+
307
+ ### Table of contents
308
+
309
+ - [Start here](#start-here)
310
+ - [Promessa e limites](#promessa-e-limites)
311
+ - [Dicionario oficial](#dicionario-oficial)
312
+ - [Status model](#status-model)
313
+ - [Checklist corporativo pre-flight](#checklist-corporativo-pre-flight)
314
+ - [Guia operacional (produto)](#guia-operacional-produto)
315
+ - [Controle de entrada e saida](#controle-de-entrada-e-saida)
316
+ - [Precedencia de modo e fluxo de render](#precedencia-de-modo-e-fluxo-de-render)
317
+ - [Persistencia, identidade e compatibilidade](#persistencia-identidade-e-compatibilidade)
318
+ - [Controle de comportamento](#controle-de-comportamento)
319
+ - [Acessibilidade e motion](#acessibilidade-e-motion)
320
+ - [Conteudo dinamico e widgets](#conteudo-dinamico-e-widgets)
321
+ - [Operacao em runtime (editor, quick setup, AI)](#operacao-em-runtime-editor-quick-setup-ai)
322
+ - [Contrato tecnico completo (referencia)](#contrato-tecnico-completo-referencia)
323
+ - [Interfaces do contrato](#interfaces-do-contrato)
324
+ - [Matriz top-level](#matriz-top-level)
325
+ - [Appearance API (deep dive)](#appearance-api-deep-dive)
326
+ - [Behavior API](#behavior-api)
327
+ - [Accessibility API](#accessibility-api)
328
+ - [Group API (`group` + `tabs[]`)](#group-api-group--tabs)
329
+ - [Nav API (`nav` + `links[]`)](#nav-api-nav--links)
330
+ - [Complete JSON path index](#complete-json-path-index)
331
+ - [Styling](#styling)
332
+ - [Examples](#examples)
333
+ - [Known limitations and mismatches](#known-limitations-and-mismatches)
334
+ - [Source references](#source-references)
335
+ - [Referencias oficiais Angular](#referencias-oficiais-angular)
336
+
337
+ ### Start here
338
+
339
+ #### Promessa e limites
340
+
341
+ **O que isso habilita:** composicao de tabs por contrato JSON, com dois modos (`group` e `nav`) e integracao nativa com widgets Praxis.
342
+
343
+ **Quando usar:** quando o objetivo e evoluir fluxo de tela por configuracao (config-first), sem replicar logica de UI em cada feature.
344
+
345
+ **Exemplo minimo:** defina `group + tabs[]` para fluxo simples ou `nav + links[]` para shell modular.
346
+
347
+ Garantias principais (hoje):
348
+
349
+ - Precedencia explicita de modo de render.
350
+ - Clamp de indices de selecao.
351
+ - Persistencia por identidade (`tabsId` + `componentInstanceId` + rota).
352
+ - Reemissao de eventos de widgets com contexto (`tabId/tabIndex` ou `linkId/linkIndex`).
353
+
354
+ Limites explicitos (hoje):
355
+
356
+ - Alguns campos existem para compatibilidade futura e ainda nao mudam o runtime.
357
+ - `events` e placeholder de contrato (nao aciona runtime por si).
358
+ - Em coexistencia `tabs[]` + `nav.links[]`, o modo `nav` vence por precedencia.
359
+
360
+ #### Dicionario oficial
361
+
362
+ Use estes termos como linguagem padrao da plataforma:
363
+
364
+ - `config-first`: comportamento nasce do JSON, nao de branching em template.
365
+ - `metadata-driven`: estrutura e regras sao dados versionaveis.
366
+ - `runtime de UI`: motor que interpreta contrato e renderiza.
367
+ - `policy-ready`: contrato com precedencia, limites e pontos de governanca.
368
+ - `compatibilidade`: campos declarados podem existir antes do binding de runtime.
369
+ - `garantia`: comportamento confirmado por implementacao ativa.
370
+
371
+ #### Status model
372
+
373
+ Padrao oficial para cada recurso/campo:
374
+
375
+ - `Status: Active` - funciona no runtime atual.
376
+ - `Status: Partial` - parte ativa, parte ainda sem binding.
377
+ - `Status: Derived` - nao e configurado de forma autoritativa, mas o runtime calcula o valor a partir de outro estado.
378
+ - `Status: Stored-only` - persiste no config, sem efeito direto na UI.
379
+ - `Status: Declared-only` - declarado em tipos/schema sem binding publico confirmado.
380
+
381
+ #### Checklist corporativo pre-flight
382
+
383
+ - Defina `tabsId` estavel por tela.
384
+ - Em multi-instancia na mesma rota, use `componentInstanceId`.
385
+ - Mantenha ids unicos em `tabs[].id` e `nav.links[].id`.
386
+ - Para `behavior.lazyLoad=true`, valide UX da primeira ativacao em abas pesadas.
387
+ - Restrinja origem de `appearance.customCss` em ambientes com governanca de seguranca.
388
+ - Valide payload de `widgetEvent` no host antes de executar regra de negocio.
389
+
390
+ ### Guia operacional (produto)
391
+
392
+ #### Controle de entrada e saida
393
+
394
+ **O que isso habilita:** contrato claro entre host e runtime (`inputs`) e telemetria/eventos (`outputs`).
395
+
396
+ **Quando usar:** em telas que precisam integrar tabs com formulario, widgets e analytics de interacao.
397
+
398
+ **Exemplo minimo:** passar `config`, `tabsId`, `form` e escutar `(widgetEvent)`.
399
+
400
+ `Status: Active`.
401
+
402
+ ##### Component inputs
403
+
404
+ | Input | Tipo | Required | Default | O que controla | Status |
405
+ | --- | --- | --- | --- | --- | --- |
406
+ | `config` | `TabsMetadata \| null` | No | `null` | Contrato JSON principal | Active |
407
+ | `tabsId` | `string` | Sim (logico) | sem default | Identidade para persistencia | Active |
408
+ | `componentInstanceId` | `string \| undefined` | No | `undefined` | Isolamento de instancias iguais | Active |
409
+ | `enableCustomization` | `boolean` | No | `false` | FAB de edicao + quick setup + AI assistant | Active |
410
+ | `form` | `FormGroup \| null` | No | `null` | Base para `content` dinamico | Active |
411
+ | `context` | `Record<string, any> \| null` | No | `null` | Contexto entregue aos widgets internos | Active |
412
+
413
+ Notas operacionais:
414
+
415
+ - `content` nao renderiza se `form` for `null`.
416
+ - `widgets` renderizam com fallback de contexto para `{}`.
417
+
418
+ ##### Component outputs
419
+
420
+ | Output | Payload | Quando dispara | Status |
421
+ | --- | --- | --- | --- |
422
+ | `animationDone` | `void` | Final da animacao no `mat-tab-group` | Active |
423
+ | `focusChange` | `MatTabChangeEvent` | Mudanca de foco em aba (group) | Active |
424
+ | `selectedIndexChange` | `number` | Selecao em `onSelectedIndexChange` (group) e `onNavClick` (nav) | Active |
425
+ | `selectedTabChange` | `MatTabChangeEvent` | Troca de aba no `mat-tab-group` | Active |
426
+ | `indexFocused` | `number` | Evento nativo de foco indexado (Material) | Active |
427
+ | `selectFocusedIndex` | `number` | Evento nativo de selecao por foco (Material) | Active |
428
+ | `widgetEvent` | `{ tabId?, tabIndex?, linkId?, linkIndex?, sourceId, output?, payload? }` | Reemissao de evento vindo de widget interno com contexto de localizacao | Active |
429
+
430
+ #### Precedencia de modo e fluxo de render
431
+
432
+ **O que isso habilita:** decisao deterministica de runtime entre `group mode` e `nav mode`.
433
+
434
+ **Quando usar:** quando o mesmo componente precisa alternar de UX por contrato, sem trocar codigo host.
435
+
436
+ **Exemplo minimo:** defina `nav.links[]`; se vazio, runtime usa `tabs[]`.
437
+
438
+ `Status: Active`.
439
+
440
+ Precedencia de render:
441
+
442
+ 1. Se `config.nav.links.length > 0`, entra em `nav mode`.
443
+ 2. Caso contrario, usa `group mode`.
444
+
445
+ Fluxo simplificado:
446
+
447
+ 1. Recebe `config`.
448
+ 2. Normaliza indices com clamp.
449
+ 3. Resolve modo por precedencia.
450
+ 4. Renderiza `content` e `widgets` por aba/link.
451
+ 5. Persiste estado/config quando chave de storage existe.
452
+
453
+ #### Persistencia, identidade e compatibilidade
454
+
455
+ **O que isso habilita:** estado de selecao e configuracao consistentes entre sessoes e contextos.
456
+
457
+ **Quando usar:** em produtos com multi-tela, multi-instancia e operacao por settings panel.
458
+
459
+ **Exemplo minimo:** usar `tabsId` estavel + `componentInstanceId` para diferenciar instancias.
460
+
461
+ `Status: Active`.
462
+
463
+ - Chave de persistencia: `tabs:<componentKeyId>`.
464
+ - `componentKeyId` deriva de:
465
+ - `componentType='praxis-tabs'`
466
+ - `tabsId`
467
+ - `componentInstanceId`
468
+ - contexto de rota (`ActivatedRoute`)
469
+
470
+ Pontos que persistem config/estado:
471
+
472
+ - `ngOnChanges(config)`
473
+ - `onSelectedIndexChange`
474
+ - `onNavClick`
475
+ - `onNavDrop`
476
+ - `closeTab`
477
+ - `moveTab`
478
+ - `applyConfigFromAdapter`
479
+ - callbacks `applied$` e `saved$` do editor/quick setup
480
+
481
+ Sem `tabsId` valido:
482
+
483
+ - runtime segue funcional,
484
+ - mas nao persiste,
485
+ - e registra warning deduplicado via `LoggerService.warnOnce`.
486
+
487
+ #### Controle de comportamento
488
+
489
+ **O que isso habilita:** ligamento declarativo de lazy load, fechamento e reorder por JSON.
490
+
491
+ **Quando usar:** quando UX de operacao muda por tela, mas com o mesmo runtime.
492
+
493
+ **Exemplo minimo:** `"behavior": { "lazyLoad": true, "closeable": true }`.
494
+
495
+ `Status: Active`.
496
+
497
+ | Campo | Tipo | Efeito | Status |
498
+ | --- | --- | --- | --- |
499
+ | `behavior.lazyLoad` | `boolean` | Render sob demanda por primeira ativacao | Active |
500
+ | `behavior.closeable` | `boolean` | Exibe botao de fechar em labels de tab | Active |
501
+ | `behavior.reorderable` | `boolean` | Nav com drag-drop e group com mover esquerda/direita | Active |
502
+
503
+ #### Acessibilidade e motion
504
+
505
+ **O que isso habilita:** modo de contraste/movimento reduzido e atributos ARIA de grupo/tab.
506
+
507
+ **Quando usar:** em contextos WCAG e politicas corporativas de acessibilidade.
508
+
509
+ **Exemplo minimo:** `"accessibility": { "highContrast": true, "reduceMotion": true }`.
510
+
511
+ `Status: Partial`.
512
+
513
+ Ativo no runtime:
514
+
515
+ - `accessibility.highContrast` -> classe `high-contrast`
516
+ - `accessibility.reduceMotion` -> classe `reduce-motion` + `effectiveAnimationDuration=0ms`
517
+ - `group.ariaLabel`, `group.ariaLabelledby`
518
+ - `tabs[].ariaLabel`, `tabs[].ariaLabelledby`
519
+
520
+ Ainda sem binding direto:
521
+
522
+ - `accessibility.ariaLabels`
523
+ - `accessibility.keyboardNavigation`
524
+
525
+ #### Conteudo dinamico e widgets
526
+
527
+ **O que isso habilita:** tabs como host de formulario dinamico e modulos ricos, sem acoplamento no template host.
528
+
529
+ **Quando usar:** quando cada aba/link precisa conter componentes heterogeneos e eventos de negocio.
530
+
531
+ **Exemplo minimo:** `tabs[].widgets` com `praxis-table`, `praxis-list` ou `praxis-crud`.
532
+
533
+ `Status: Active`.
534
+
535
+ Duas estrategias por aba/link:
536
+
537
+ 1. **Campos dinamicos (`content`)**
538
+ - esperado: metadata de fields
539
+ - render: `DynamicFieldLoaderDirective`
540
+ - prerequisito: `form` fornecido pelo host
541
+
542
+ 2. **Widgets (`widgets`)**
543
+ - esperado: `WidgetDefinition[]`
544
+ - render: `DynamicWidgetLoaderDirective`
545
+ - contexto: `context` (fallback `{}`)
546
+
547
+ Formato de `widgetEvent`:
548
+
549
+ - group mode: `{ tabId, tabIndex, sourceId, output, payload }`
550
+ - nav mode: `{ linkId, linkIndex, sourceId, output, payload }`
551
+
552
+ #### Operacao em runtime (editor, quick setup, AI)
553
+
554
+ **O que isso habilita:** ciclo config-first completo (criar, editar, ajustar e versionar contrato).
555
+
556
+ **Quando usar:** em squads que precisam reduzir tempo de mudanca de UI sem rebuild completo.
557
+
558
+ **Exemplo minimo:** `enableCustomization=true` para habilitar editor, quick setup e assistente AI.
559
+
560
+ `Status: Active`.
561
+
562
+ Fluxos disponiveis:
563
+
564
+ 1. **Editor completo (`PraxisTabsConfigEditor`)**
565
+ - id: `praxis-tabs-editor:<key>`
566
+ - cobre comportamento, estilo, tabs, links e widgets
567
+ - sincroniza por `applied$` e `saved$`
568
+
569
+ 2. **Quick setup (`TabsQuickSetupComponent`)**
570
+ - id: `praxis-tabs-quick-setup:<key>`
571
+ - bootstrap rapido de `group+tabs` ou `nav+links`
572
+ - normaliza labels e descarta vazios
573
+
574
+ 3. **Semantic assistant (`PraxisAiAssistantShellComponent` + `TabsAgenticAuthoringTurnFlow` + `TabsAiAdapter`)**
575
+ - abre shell compartilhado e registra sessao global quando `enableCustomization=true`
576
+ - rejeita patch JSON livre
577
+ - exige `componentEditPlan` manifest-backed antes de qualquer apply local
578
+ - roteia prompts de regra/governanca para `domain-rules/intake`
579
+
580
+ Governanca recomendada:
581
+
582
+ - tratar AI como acelerador de autoria, nao como bypass de validacao.
583
+ - manter revisao funcional com base em contrato e limites ativos.
584
+
585
+ ### Contrato tecnico completo (referencia)
586
+
587
+ #### Interfaces do contrato
588
+
589
+ **O que isso habilita:** contrato tipado para autoria, validacao e compatibilidade.
590
+
591
+ **Quando usar:** em validadores, geradores de config, editors e testes de regressao.
592
+
593
+ **Exemplo minimo:** `TabsMetadata` como payload unico do runtime.
594
+
595
+ ```ts
596
+ interface TabsMetadata {
597
+ meta?: any;
598
+ appearance?: TabsAppearanceConfig;
599
+ behavior?: TabsBehaviorConfig;
600
+ events?: TabsEventConfig;
601
+ accessibility?: TabsAccessibilityConfig;
602
+ group?: TabGroupMetadata;
603
+ tabs?: TabMetadata[];
604
+ nav?: TabNavMetadata;
605
+ }
606
+ ```
607
+
608
+ #### Matriz top-level
609
+
610
+ **O que isso habilita:** leitura executiva do que esta ativo, parcial, armazenado ou apenas declarado.
611
+
612
+ **Quando usar:** em onboarding tecnico e revisao de impacto de mudanca.
613
+
614
+ **Exemplo minimo:** revisar `behavior`, `group/tabs`, `nav/links` antes de configurar.
615
+
616
+ | Caminho | Status | Observacao |
617
+ | --- | --- | --- |
618
+ | `meta` | Stored-only | Bag livre, sem consumo direto no runtime |
619
+ | `appearance` | Partial | Maioria ativa; parte dos tokens e declarativa |
620
+ | `behavior` | Active | Lazy load, close e reorder ativos |
621
+ | `events` | Stored-only | Placeholder de contrato |
622
+ | `accessibility` | Partial | `highContrast/reduceMotion` ativos |
623
+ | `group` | Partial | Quase completo; `contentTabIndex` sem binding |
624
+ | `tabs[]` | Partial | Principal ativo; alguns campos sao metadado |
625
+ | `nav` | Partial | Principal ativo; `links[].active` sem binding |
626
+
627
+ #### Appearance API (deep dive)
628
+
629
+ **O que isso habilita:** densidade, tema e estilo runtime por instancia.
630
+
631
+ **Quando usar:** para padronizar visual sem duplicar CSS por tela.
632
+
633
+ **Exemplo minimo:** `appearance.density` + `appearance.tokens`.
634
+
635
+ Campos:
636
+
637
+ - `density`
638
+ - `themeClass`
639
+ - `customCss`
640
+ - `tokens`
641
+
642
+ ##### density
643
+
644
+ | Campo | Opcoes | Status | Runtime |
645
+ | --- | --- | --- | --- |
646
+ | `appearance.density` | `compact \| comfortable \| spacious` | Active | classes `density-*` |
647
+
648
+ ##### themeClass
649
+
650
+ | Campo | Status | Runtime |
651
+ | --- | --- | --- |
652
+ | `appearance.themeClass` | Active | `[ngClass]` no root |
653
+
654
+ ##### customCss
655
+
656
+ | Campo | Status | Runtime |
657
+ | --- | --- | --- |
658
+ | `appearance.customCss` | Active | Aplicado via `safeCustomCss()` |
659
+
660
+ Politica de bloqueio atual:
661
+
662
+ - bloqueia `@import`
663
+ - bloqueia `expression(`
664
+ - bloqueia `behavior:`
665
+ - bloqueia `</style`
666
+ - bloqueia `<script`
667
+ - bloqueia `url(javascript:...)`
668
+ - bloqueia `url(data:text/html...)`
669
+
670
+ ##### tokens (runtime CSS)
671
+
672
+ Tokens mapeados no runtime:
673
+
674
+ - `active-indicator-color`
675
+ - `active-focus-indicator-color`
676
+ - `active-hover-indicator-color`
677
+ - `active-label-text-color`
678
+ - `active-focus-label-text-color`
679
+ - `active-hover-label-text-color`
680
+ - `inactive-label-text-color`
681
+ - `inactive-hover-label-text-color`
682
+ - `inactive-focus-label-text-color`
683
+ - `pagination-icon-color`
684
+ - `divider-color`
685
+ - `background-color`
686
+
687
+ Token declarado sem efeito atual:
688
+
689
+ - `inactive-ripple-color` (`Status: Declared-only`)
690
+
691
+ Escopo de estilo:
692
+
693
+ - seletor base: `.praxis-tabs-root[data-tabs-id="<scope>"]`
694
+ - `<scope>` e sanitizado de `tabsId + componentInstanceId`
695
+
696
+ #### Behavior API
697
+
698
+ **O que isso habilita:** toggle declarativo de comportamento central do runtime.
699
+
700
+ **Quando usar:** para ajustar UX por tela sem ramificar componente host.
701
+
702
+ **Exemplo minimo:** habilitar `lazyLoad` em abas pesadas.
703
+
704
+ | Campo | Tipo | Status |
705
+ | --- | --- | --- |
706
+ | `behavior.lazyLoad` | `boolean` | Active |
707
+ | `behavior.closeable` | `boolean` | Active |
708
+ | `behavior.reorderable` | `boolean` | Active |
709
+
710
+ Detalhes:
711
+
712
+ - `closeable` mostra botao de fechar no label de tab.
713
+ - `reorderable`:
714
+ - nav: drag-and-drop horizontal (`cdkDropList`)
715
+ - group: botoes esquerda/direita no label da tab
716
+
717
+ #### Accessibility API
718
+
719
+ **O que isso habilita:** contrato unico para requisitos de acessibilidade.
720
+
721
+ **Quando usar:** em times com gate WCAG e criterios de release por a11y.
722
+
723
+ **Exemplo minimo:** `highContrast` + `reduceMotion`.
724
+
725
+ | Campo | Status | Observacao |
726
+ | --- | --- | --- |
727
+ | `accessibility.highContrast` | Active | classe `high-contrast` |
728
+ | `accessibility.reduceMotion` | Active | classe `reduce-motion` + `effectiveAnimationDuration=0ms` |
729
+ | `accessibility.ariaLabels` | Declared-only | manter fora do contrato publico ate existir binding |
730
+ | `accessibility.keyboardNavigation` | Declared-only | manter fora do contrato publico ate existir binding |
731
+
732
+ Atributos ARIA ativos via `group`/`nav`/`tabs`:
733
+
734
+ - `group.ariaLabel`
735
+ - `group.ariaLabelledby`
736
+ - `nav.ariaLabel`
737
+ - `nav.ariaLabelledby`
738
+ - `tabs[].ariaLabel`
739
+ - `tabs[].ariaLabelledby`
740
+
741
+ #### Group API (`group` + `tabs[]`)
742
+
743
+ **O que isso habilita:** modo classico de tabs com cabecalho/conteudo no `mat-tab-group`.
744
+
745
+ **Quando usar:** para fluxos por secao com trocas previsiveis no mesmo contexto de pagina.
746
+
747
+ **Exemplo minimo:** `group.selectedIndex` + `tabs[].textLabel`.
748
+
749
+ ##### `group`
750
+
751
+ | Caminho | Status | Runtime |
752
+ | --- | --- | --- |
753
+ | `group.alignTabs` | Active | `mat-align-tabs` |
754
+ | `group.animationDuration` | Active | `effectiveAnimationDuration()` |
755
+ | `group.ariaLabel` | Active | atributo no `mat-tab-group` |
756
+ | `group.ariaLabelledby` | Active | atributo no `mat-tab-group` |
757
+ | `group.color` | Active | prop Material M2 |
758
+ | `group.backgroundColor` | Active | prop Material M2 |
759
+ | `group.contentTabIndex` | Declared-only | sem binding no template |
760
+ | `group.disablePagination` | Active | prop `mat-tab-group` |
761
+ | `group.disableRipple` | Active | prop `mat-tab-group` |
762
+ | `group.dynamicHeight` | Active | prop `mat-tab-group` |
763
+ | `group.fitInkBarToContent` | Active | prop `mat-tab-group` |
764
+ | `group.headerPosition` | Active | prop `mat-tab-group` |
765
+ | `group.preserveContent` | Active | prop `mat-tab-group` |
766
+ | `group.selectedIndex` | Active | estado interno + persistencia + clamp |
767
+ | `group.stretchTabs` | Active | `mat-stretch-tabs` |
768
+
769
+ ##### `tabs[]`
770
+
771
+ | Caminho | Status | Runtime |
772
+ | --- | --- | --- |
773
+ | `tabs[].id` | Active | id da tab + contexto de evento |
774
+ | `tabs[].ariaLabel` | Active | atributo por tab |
775
+ | `tabs[].ariaLabelledby` | Active | atributo por tab |
776
+ | `tabs[].textLabel` | Active | label exibido |
777
+ | `tabs[].labelClass` | Active | classe de label |
778
+ | `tabs[].bodyClass` | Active | classe de body |
779
+ | `tabs[].disabled` | Active | desabilita tab |
780
+ | `tabs[].content` | Active | `DynamicFieldLoaderDirective` (requer `form`) |
781
+ | `tabs[].widgets` | Active | `DynamicWidgetLoaderDirective` |
782
+ | `tabs[].isActive` | Declared-only | sem binding direto |
783
+ | `tabs[].origin` | Declared-only | sem binding direto |
784
+ | `tabs[].position` | Declared-only | sem binding direto |
785
+
786
+ #### Nav API (`nav` + `links[]`)
787
+
788
+ **O que isso habilita:** modo de navegacao por links com painel unificado e reorder por drag.
789
+
790
+ **Quando usar:** para shells de pagina e navegacao horizontal mais proxima de menu.
791
+
792
+ **Exemplo minimo:** `nav.selectedIndex` + `nav.links[]`.
793
+
794
+ ##### `nav`
795
+
796
+ | Caminho | Status | Runtime |
797
+ | --- | --- | --- |
798
+ | `nav.animationDuration` | Active | `effectiveAnimationDuration()` |
799
+ | `nav.ariaLabel` | Active | atributo no `mat-tab-nav-bar` |
800
+ | `nav.ariaLabelledby` | Active | atributo no `mat-tab-nav-bar` |
801
+ | `nav.color` | Active | prop Material Nav |
802
+ | `nav.backgroundColor` | Active | prop Material Nav |
803
+ | `nav.disablePagination` | Active | prop Material Nav |
804
+ | `nav.disableRipple` | Active | prop Material Nav |
805
+ | `nav.fitInkBarToContent` | Active | prop Material Nav |
806
+ | `nav.selectedIndex` | Active | estado interno + persistencia + clamp |
807
+ | `nav.stretchTabs` | Active | prop Material Nav |
808
+ | `nav.links` | Active | fonte de nav mode |
809
+
810
+ ##### `nav.links[]`
811
+
812
+ | Caminho | Status | Runtime |
813
+ | --- | --- | --- |
814
+ | `nav.links[].id` | Active | preservacao de selecao no reorder + contexto |
815
+ | `nav.links[].label` | Active | label exibido |
816
+ | `nav.links[].active` | Derived | ativo real e derivado de `currentNavIndex` |
817
+ | `nav.links[].disabled` | Active | desabilita link |
818
+ | `nav.links[].disableRipple` | Active | override por link |
819
+ | `nav.links[].fitInkBarToContent` | Active | override por link |
820
+ | `nav.links[].content` | Active | `DynamicFieldLoaderDirective` (requer `form`) |
821
+ | `nav.links[].widgets` | Active | `DynamicWidgetLoaderDirective` |
822
+
823
+ #### Complete JSON path index
824
+
825
+ | JSON path | Status | Observacao |
826
+ | --- | --- | --- |
827
+ | `meta` | Stored-only | bag livre sem binding direto |
828
+ | `appearance` | Partial | bloco ativo com ressalvas em token |
829
+ | `appearance.density` | Active | classes `density-*` |
830
+ | `appearance.themeClass` | Active | classe no root |
831
+ | `appearance.customCss` | Active | filtrado por seguranca |
832
+ | `appearance.tokens` | Active | mapeado por `styleCss()` |
833
+ | `appearance.tokens.active-indicator-color` | Active | css runtime |
834
+ | `appearance.tokens.active-focus-indicator-color` | Active | css runtime |
835
+ | `appearance.tokens.active-hover-indicator-color` | Active | css runtime |
836
+ | `appearance.tokens.active-label-text-color` | Active | css runtime |
837
+ | `appearance.tokens.active-focus-label-text-color` | Active | css runtime |
838
+ | `appearance.tokens.active-hover-label-text-color` | Active | css runtime |
839
+ | `appearance.tokens.inactive-label-text-color` | Active | css runtime |
840
+ | `appearance.tokens.inactive-hover-label-text-color` | Active | css runtime |
841
+ | `appearance.tokens.inactive-focus-label-text-color` | Active | css runtime |
842
+ | `appearance.tokens.inactive-ripple-color` | Declared-only | nao mapeado no render atual |
843
+ | `appearance.tokens.pagination-icon-color` | Active | css runtime |
844
+ | `appearance.tokens.divider-color` | Active | css runtime |
845
+ | `appearance.tokens.background-color` | Active | css runtime |
846
+ | `behavior` | Active | bloco runtime |
847
+ | `behavior.lazyLoad` | Active | lazy content |
848
+ | `behavior.closeable` | Active | fechar aba |
849
+ | `behavior.reorderable` | Active | reorder nav/group |
850
+ | `events` | Stored-only | placeholder |
851
+ | `accessibility` | Partial | parcial |
852
+ | `accessibility.ariaLabels` | Declared-only | nao expor como contrato publico |
853
+ | `accessibility.keyboardNavigation` | Declared-only | nao expor como contrato publico |
854
+ | `accessibility.highContrast` | Active | classe root |
855
+ | `accessibility.reduceMotion` | Active | classe root + duracao |
856
+ | `group` | Partial | quase completo |
857
+ | `group.alignTabs` | Active | material prop |
858
+ | `group.animationDuration` | Active | runtime duration |
859
+ | `group.ariaLabel` | Active | aria attr |
860
+ | `group.ariaLabelledby` | Active | aria attr |
861
+ | `group.color` | Active | material M2 |
862
+ | `group.contentTabIndex` | Declared-only | sem binding |
863
+ | `nav.ariaLabel` | Active | aria attr |
864
+ | `nav.ariaLabelledby` | Active | aria attr |
865
+ | `group.disablePagination` | Active | material prop |
866
+ | `group.disableRipple` | Active | material prop |
867
+ | `group.dynamicHeight` | Active | material prop |
868
+ | `group.fitInkBarToContent` | Active | material prop |
869
+ | `group.headerPosition` | Active | material prop |
870
+ | `group.preserveContent` | Active | material prop |
871
+ | `group.selectedIndex` | Active | clamp + persist |
872
+ | `group.stretchTabs` | Active | material prop |
873
+ | `group.backgroundColor` | Active | material M2 |
874
+ | `tabs` | Partial | principal ativo |
875
+ | `tabs[].id` | Active | id/ctx |
876
+ | `tabs[].ariaLabel` | Active | aria attr |
877
+ | `tabs[].ariaLabelledby` | Active | aria attr |
878
+ | `tabs[].textLabel` | Active | label |
879
+ | `tabs[].labelClass` | Active | class |
880
+ | `tabs[].bodyClass` | Active | class |
881
+ | `tabs[].disabled` | Active | disable |
882
+ | `tabs[].content` | Active | dynamic fields |
883
+ | `tabs[].widgets` | Active | dynamic widgets |
884
+ | `tabs[].isActive` | Declared-only | sem binding |
885
+ | `tabs[].origin` | Declared-only | sem binding |
886
+ | `tabs[].position` | Declared-only | sem binding |
887
+ | `nav` | Partial | principal ativo |
888
+ | `nav.animationDuration` | Active | runtime duration |
889
+ | `nav.color` | Active | material nav |
890
+ | `nav.backgroundColor` | Active | material nav |
891
+ | `nav.disablePagination` | Active | material nav |
892
+ | `nav.disableRipple` | Active | material nav |
893
+ | `nav.fitInkBarToContent` | Active | material nav |
894
+ | `nav.selectedIndex` | Active | clamp + persist |
895
+ | `nav.stretchTabs` | Active | material nav |
896
+ | `nav.links` | Active | fonte do modo nav |
897
+ | `nav.links[].id` | Active | merge/reorder context |
898
+ | `nav.links[].label` | Active | label |
899
+ | `nav.links[].active` | Derived | derivado por indice |
900
+ | `nav.links[].disabled` | Active | disable |
901
+ | `nav.links[].disableRipple` | Active | override |
902
+ | `nav.links[].fitInkBarToContent` | Active | override |
903
+ | `nav.links[].content` | Active | dynamic fields |
904
+ | `nav.links[].widgets` | Active | dynamic widgets |
905
+
906
+ ### Styling
907
+
908
+ Camadas de estilo no runtime:
909
+
910
+ 1. classes de densidade/acessibilidade no root
911
+ 2. `themeClass` opcional
912
+ 3. CSS custom filtrado (`customCss`)
913
+ 4. CSS de tokens gerado em runtime (`styleCss`)
914
+
915
+ Boas praticas corporativas:
916
+
917
+ - prefira `appearance.tokens` para ajustes tematicos
918
+ - use `customCss` so para excecoes governadas
919
+ - mantenha `tabsId` estavel para escopo visual previsivel
920
+
921
+ ### Examples
922
+
923
+ ### Minimal valid
924
+
925
+ ```json
926
+ {
927
+ "behavior": { "lazyLoad": true },
928
+ "group": { "selectedIndex": 0, "stretchTabs": true },
929
+ "tabs": [
930
+ { "id": "dados", "textLabel": "Dados" },
931
+ { "id": "itens", "textLabel": "Itens" }
932
+ ]
933
+ }
934
+ ```
935
+
936
+ ### Typical/common
937
+
938
+ ```json
939
+ {}
940
+ ```
941
+
942
+ ### Advanced
943
+
944
+ ```json
945
+ {}
946
+ ```
947
+
948
+ ### Enterprise scenario
949
+
950
+ ```json
951
+ {}
952
+ ```
953
+
954
+ ## Known limitations and mismatches
955
+
956
+ | Path/Behavior | Observed behavior (runtime) | Desired behavior | Impact | Tracking issue | Target fix |
957
+ | --- | --- | --- | --- | --- | --- |
958
+ | coverage/mapping | Evidência textual preservada indica itens Partial/Declared-only. | Cobertura confirmada por evidência runtime + schema + editor. | Pode gerar uso de paths não totalmente ligados. | to-be-linked | next-doc-cycle |
959
+
960
+ ## Compatibility and migration notes
961
+
962
+ | Concern | Affected versions | Migration action | Deadline | Notes |
963
+ | --- | --- | --- | --- | --- |
964
+ | legacy aliases and mixed status vocabulary | pre-canonical docs | manter apenas taxonomia canonica nas secoes novas e reduzir termos legados em revisoes incrementais | ongoing | backward compatibility documental ainda existe em secoes historicas |
965
+
966
+ ## Source references
967
+
968
+ | Source type | Path/URL | Why it is source of truth | Last verified (YYYY-MM-DD) | Notes |
969
+ | --- | --- | --- | --- | --- |
970
+ | local-file | projects/praxis-tabs/src/lib/praxis-tabs.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
971
+ | local-file | projects/praxis-tabs/src/lib/praxis-tabs.spec.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
972
+ | local-file | projects/praxis-tabs/src/lib/praxis-tabs-widget-event.spec.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
973
+ | local-file | projects/praxis-tabs/src/lib/praxis-tabs.metadata.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
974
+ | local-file | projects/praxis-tabs/src/lib/praxis-tabs-config-editor.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
975
+ | local-file | projects/praxis-tabs/src/lib/quick-setup/tabs-quick-setup.component.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
976
+ | local-file | projects/praxis-tabs/src/lib/ai/tabs-ai.adapter.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
977
+ | local-file | projects/praxis-tabs/src/lib/ai/tabs-ai-capabilities.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
978
+ | local-file | projects/praxis-tabs/src/lib/ai/tabs-context-pack.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |