@praxisui/table 9.0.68-rc.3 → 10.0.0-rc.3

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.
@@ -1,6 +1,6 @@
1
1
  import { Observable, firstValueFrom } from 'rxjs';
2
2
  import { withAuthoringScopePolicy } from '@praxisui/ai';
3
- import { af as setTableActionGlobalActionRef } from './praxisui-table-praxisui-table-EGWwY1dR.mjs';
3
+ import { af as setTableActionGlobalActionRef } from './praxisui-table-praxisui-table-DKvwb6v1.mjs';
4
4
 
5
5
  class TableAgenticAuthoringTurnFlow {
6
6
  adapter;
@@ -1,7 +1,7 @@
1
1
  import { firstValueFrom } from 'rxjs';
2
2
  import { BaseAiAdapter, sanitizePraxisAssistantText, createComponentAuthoringContext } from '@praxisui/ai';
3
3
  import { PRAXIS_GLOBAL_ACTION_CATALOG, deepMerge } from '@praxisui/core';
4
- import { L as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, n as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, $ as coerceTableComponentEditPlans, a1 as compileTableComponentEditPlans, Q as TASK_PRESETS, a6 as getTableComponentEditPlanCapabilities, H as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, E as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, I as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, O as TABLE_COMPONENT_EDIT_PLAN_VERSION, G as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, K as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-EGWwY1dR.mjs';
4
+ import { L as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, n as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, $ as coerceTableComponentEditPlans, a1 as compileTableComponentEditPlans, Q as TASK_PRESETS, a6 as getTableComponentEditPlanCapabilities, H as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, E as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, I as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, O as TABLE_COMPONENT_EDIT_PLAN_VERSION, G as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, K as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-DKvwb6v1.mjs';
5
5
 
6
6
  const TABLE_ROW_EXPRESSION_CONTEXT_OPTION = {
7
7
  mode: 'expression',
@@ -207,15 +207,16 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
207
207
  { value: 'false', label: 'Disabled' },
208
208
  ],
209
209
  },
210
- 'behavior.expansion.detail.source.mode': {
210
+ 'behavior.detail.source.mode': {
211
211
  mode: 'enum',
212
212
  options: [
213
213
  { value: 'inline', label: 'Inline' },
214
214
  { value: 'resource', label: 'Resource' },
215
215
  { value: 'resourcePath', label: 'Resource Path' },
216
+ { value: 'hypermedia', label: 'Hypermedia' },
216
217
  ],
217
218
  },
218
- 'behavior.expansion.detail.source.resource.kind': {
219
+ 'behavior.detail.source.resource.kind': {
219
220
  mode: 'enum',
220
221
  options: [
221
222
  { value: 'ui-composition', label: 'UI Composition' },
@@ -224,34 +225,34 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
224
225
  { value: 'dashboard-schema', label: 'Dashboard Schema' },
225
226
  ],
226
227
  },
227
- 'behavior.expansion.detail.source.resourcePath.method': {
228
+ 'behavior.detail.source.resourcePath.method': {
228
229
  mode: 'enum',
229
230
  options: [
230
231
  { value: 'GET', label: 'GET' },
231
232
  { value: 'POST', label: 'POST' },
232
233
  ],
233
234
  },
234
- 'behavior.expansion.detail.source.resourcePath.paramsMap': {
235
+ 'behavior.detail.source.resourcePath.paramsMap': {
235
236
  mode: 'suggested',
236
237
  options: [
237
238
  { value: '{"id":"$row.id"}', label: 'Row ID' },
238
239
  { value: '{"id":"$row.id","table":"$ctx.tableId"}', label: 'Row + Table' },
239
240
  ],
240
241
  },
241
- 'behavior.expansion.detail.source.resourceAllowList[]': {
242
+ 'behavior.detail.source.resourceAllowList[]': {
242
243
  mode: 'suggested',
243
244
  options: [
244
245
  { value: 'api/orders/*/detail-schema', label: 'Orders detail schema' },
245
246
  { value: 'api/customers/*/detail-schema', label: 'Customers detail schema' },
246
247
  ],
247
248
  },
248
- 'behavior.expansion.detail.rendering.strategy': {
249
+ 'behavior.detail.rendering.strategy': {
249
250
  mode: 'enum',
250
251
  options: [
251
252
  { value: 'registry', label: 'Registry' },
252
253
  ],
253
254
  },
254
- 'behavior.expansion.detail.rendering.hostLayout': {
255
+ 'behavior.detail.rendering.hostLayout': {
255
256
  mode: 'enum',
256
257
  options: [
257
258
  { value: 'auto', label: 'Auto' },
@@ -259,14 +260,14 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
259
260
  { value: 'tabs', label: 'Tabs' },
260
261
  ],
261
262
  },
262
- 'behavior.expansion.detail.rendering.fallbackNodePolicy': {
263
+ 'behavior.detail.rendering.fallbackNodePolicy': {
263
264
  mode: 'enum',
264
265
  options: [
265
266
  { value: 'failClosed', label: 'Fail Closed' },
266
267
  { value: 'renderPlaceholder', label: 'Render Placeholder' },
267
268
  ],
268
269
  },
269
- 'behavior.expansion.detail.height.mode': {
270
+ 'behavior.detail.height.mode': {
270
271
  mode: 'enum',
271
272
  options: [
272
273
  { value: 'fixed', label: 'Fixed' },
@@ -1349,16 +1350,16 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
1349
1350
  defaultValue: true,
1350
1351
  patchTemplate: {
1351
1352
  behavior: {
1353
+ detail: {
1354
+ schemaContract: { kind: 'praxis.detail.schema', version: '1.0.0' },
1355
+ source: { mode: 'inline', inlineSchema: { layout: 'stack', items: [] } },
1356
+ rendering: { strategy: 'registry', registryId: 'praxis.detail.default' }
1357
+ },
1352
1358
  expansion: {
1353
1359
  enabled: true,
1354
1360
  contractVersion: '1.0.0',
1355
1361
  interaction: { trigger: 'icon', keyboard: { profile: 'disclosure' } },
1356
1362
  limits: { allowMultiple: false, maxExpandedRows: 1, onOverflow: 'collapseOldest' },
1357
- detail: {
1358
- schemaContract: { kind: 'praxis.detail.schema', version: '1.0.0' },
1359
- source: { mode: 'inline', inlineSchema: { layout: 'stack', items: [] } },
1360
- rendering: { strategy: 'registry', registryId: 'praxis.detail.default' }
1361
- }
1362
1363
  }
1363
1364
  }
1364
1365
  }
@@ -1371,7 +1372,8 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
1371
1372
  operation: 'update',
1372
1373
  requiresExistingTarget: false,
1373
1374
  patchTemplate: {
1374
- behavior: { expansion: { detail: { source: { mode: '{{value}}' } } } }
1375
+ behavior: { detail: { source: { mode: '{{value}}' } },
1376
+ expansion: {} }
1375
1377
  }
1376
1378
  },
1377
1379
  {
@@ -1383,18 +1385,17 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
1383
1385
  requiresExistingTarget: false,
1384
1386
  patchTemplate: {
1385
1387
  behavior: {
1386
- expansion: {
1387
- detail: {
1388
- source: {
1389
- mode: 'resource',
1390
- resource: {
1391
- kind: '{{params.kind}}',
1392
- id: '{{params.id}}',
1393
- version: '{{params.version}}'
1394
- }
1388
+ detail: {
1389
+ source: {
1390
+ mode: 'resource',
1391
+ resource: {
1392
+ kind: '{{params.kind}}',
1393
+ id: '{{params.id}}',
1394
+ version: '{{params.version}}'
1395
1395
  }
1396
1396
  }
1397
- }
1397
+ },
1398
+ expansion: {}
1398
1399
  }
1399
1400
  }
1400
1401
  },
@@ -1681,9 +1682,9 @@ const TABLE_COMPONENT_CONTEXT_PACK = {
1681
1682
  'DOC: Widget purpose: data table with sorting, filtering, pagination, and actions.',
1682
1683
  'DOC: Host inputs: tableId (required), resourcePath (optional), config (optional).',
1683
1684
  'DOC: config defaults to createDefaultTableConfig(); columns may start empty.',
1684
- 'DOC: behavior.expansion.detail é schema-driven; altere source.mode (inline/resource/resourcePath), não use detail.type.',
1685
+ 'DOC: behavior.detail é schema-driven; altere source.mode (inline/resource/resourcePath), não use detail.type.',
1685
1686
  'DOC: Para detail.source.mode=resource, sempre informar resource.kind + resource.id + resource.version.',
1686
- 'DOC: Para detail.source.mode=resourcePath, sempre informar resourcePath.paramsMap + resourceAllowList[]; URL absoluta/scheme (http:, https:, data:, javascript:) é bloqueada e o runtime aplica fail-closed.',
1687
+ 'DOC: Para detail.source.mode=resourcePath, sempre informar resourcePath.paramsMap + resourceAllowList[] de pathname; o runtime resolve contra document.baseURI, exige origem do host, compara o pathname canonicalizado e bloqueia URL absoluta/scheme, redirects e representações ambíguas. A allowlist é guardrail do documento, não autorização nem política por método; o backend continua responsável por autorizar GET/POST.',
1687
1688
  'DOC: collapseOn ativo no runtime P0A: sortChange, pageChange, filterChange e dataRefresh.',
1688
1689
  'DOC: When resourcePath is available, the table can load schema and data; ask the user to pick an API resource when missing.',
1689
1690
  'DOC: resourcePath must be the base resource path only (no /filter, /all, /{id}). CRUD endpoints are handled internally.',
@@ -3699,8 +3700,8 @@ Columns Analysis:
3699
3700
  const warnings = [];
3700
3701
  // Some schema-driven nodes are intentionally open objects and must be preserved as-is.
3701
3702
  const passthroughObjectPaths = new Set([
3702
- 'behavior.expansion.detail.source.inlineSchema',
3703
- 'behavior.expansion.detail.source.resourcePath.paramsMap',
3703
+ 'behavior.detail.source.inlineSchema',
3704
+ 'behavior.detail.source.resourcePath.paramsMap',
3704
3705
  ]);
3705
3706
  const jsonLogicObjectPaths = new Set([
3706
3707
  'columns[].computed.expression',
@@ -1 +1 @@
1
- export { A as ANALYTICS_TABLE_ROW_KEY_FIELD, a as AnalyticsTableConfigAdapterService, b as AnalyticsTableContractService, c as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, d as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, e as ColumnsConfigEditorComponent, D as DATE_PRESETS, f as DataFormatterComponent, g as DataFormattingService, F as FORMULA_TEMPLATES, h as FilterConfigService, i as FilterSettingsComponent, j as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, k as PRAXIS_FILTER_AUTHORING_MANIFEST, l as PRAXIS_FILTER_COMPONENT_METADATA, m as PRAXIS_FILTER_VIEW_CONTEXT_SCHEMA_VERSION, n as PRAXIS_TABLE_AUTHORING_MANIFEST, o as PRAXIS_TABLE_COMPONENT_METADATA, p as PRAXIS_TABLE_TOOLBAR_APPEARANCE_PRESETS, q as PRAXIS_TABLE_TOOLBAR_DEFAULT_APPEARANCE, r as PRAXIS_TABLE_TOOLBAR_TOKEN_PRESETS, s as PraxisFilter, t as PraxisFilterWidgetConfigEditor, u as PraxisTable, v as PraxisTableConfigEditor, w as PraxisTableInlineAuthoringEditorComponent, x as PraxisTableToolbar, y as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, z as TABLE_COMPONENT_AI_CAPABILITIES, E as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, G as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, H as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, I as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, K as TABLE_COMPONENT_EDIT_PLAN_KIND, O as TABLE_COMPONENT_EDIT_PLAN_VERSION, Q as TASK_PRESETS, R as TableDefaultsProvider, U as TableRulesEditorComponent, V as ToolbarActionsEditorComponent, W as ValueMappingEditorComponent, X as VisualFormulaBuilderComponent, Y as analyticsComparisonMetricField, Z as buildTableApplyPlan, _ as coerceTableComponentEditPlan, $ as coerceTableComponentEditPlans, a0 as compileTableComponentEditPlan, a1 as compileTableComponentEditPlans, a2 as createTableAuthoringDocument, a3 as getActionId, a4 as getEnum, a5 as getTableCapabilities, a6 as getTableComponentEditPlanCapabilities, a7 as isTableRendererSupportedByRichContentP0, a8 as mapTableRendererToRichContentP0, a9 as normalizeTableAuthoringDocument, aa as parseLegacyOrTableDocument, ab as providePraxisFilterMetadata, ac as providePraxisTableMetadata, ad as providePraxisTableToolbarAppearance, ae as serializeTableAuthoringDocument, ag as toCanonicalTableConfig, ah as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-EGWwY1dR.mjs';
1
+ export { A as ANALYTICS_TABLE_ROW_KEY_FIELD, a as AnalyticsTableConfigAdapterService, b as AnalyticsTableContractService, c as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, d as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, e as ColumnsConfigEditorComponent, D as DATE_PRESETS, f as DataFormatterComponent, g as DataFormattingService, F as FORMULA_TEMPLATES, h as FilterConfigService, i as FilterSettingsComponent, j as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, k as PRAXIS_FILTER_AUTHORING_MANIFEST, l as PRAXIS_FILTER_COMPONENT_METADATA, m as PRAXIS_FILTER_VIEW_CONTEXT_SCHEMA_VERSION, n as PRAXIS_TABLE_AUTHORING_MANIFEST, o as PRAXIS_TABLE_COMPONENT_METADATA, p as PRAXIS_TABLE_TOOLBAR_APPEARANCE_PRESETS, q as PRAXIS_TABLE_TOOLBAR_DEFAULT_APPEARANCE, r as PRAXIS_TABLE_TOOLBAR_TOKEN_PRESETS, s as PraxisFilter, t as PraxisFilterWidgetConfigEditor, u as PraxisTable, v as PraxisTableConfigEditor, w as PraxisTableInlineAuthoringEditorComponent, x as PraxisTableToolbar, y as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, z as TABLE_COMPONENT_AI_CAPABILITIES, E as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, G as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, H as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, I as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, K as TABLE_COMPONENT_EDIT_PLAN_KIND, O as TABLE_COMPONENT_EDIT_PLAN_VERSION, Q as TASK_PRESETS, R as TableDefaultsProvider, U as TableRulesEditorComponent, V as ToolbarActionsEditorComponent, W as ValueMappingEditorComponent, X as VisualFormulaBuilderComponent, Y as analyticsComparisonMetricField, Z as buildTableApplyPlan, _ as coerceTableComponentEditPlan, $ as coerceTableComponentEditPlans, a0 as compileTableComponentEditPlan, a1 as compileTableComponentEditPlans, a2 as createTableAuthoringDocument, a3 as getActionId, a4 as getEnum, a5 as getTableCapabilities, a6 as getTableComponentEditPlanCapabilities, a7 as isTableRendererSupportedByRichContentP0, a8 as mapTableRendererToRichContentP0, a9 as normalizeTableAuthoringDocument, aa as parseLegacyOrTableDocument, ab as providePraxisFilterMetadata, ac as providePraxisTableMetadata, ad as providePraxisTableToolbarAppearance, ae as serializeTableAuthoringDocument, ag as toCanonicalTableConfig, ah as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-DKvwb6v1.mjs';
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@praxisui/table",
3
- "version": "9.0.68-rc.3",
3
+ "version": "10.0.0-rc.3",
4
4
  "description": "Advanced data table for Angular (Praxis UI) with editing, filtering, sorting, virtualization, and settings panel integration.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
8
  "@angular/platform-browser": "^21.0.0",
9
- "@praxisui/ai": "^9.0.68-rc.3",
10
- "@praxisui/core": "^9.0.68-rc.3",
11
- "@praxisui/dynamic-fields": "^9.0.68-rc.3",
12
- "@praxisui/dynamic-form": "^9.0.68-rc.3",
13
- "@praxisui/metadata-editor": "^9.0.68-rc.3",
14
- "@praxisui/rich-content": "^9.0.68-rc.3",
15
- "@praxisui/settings-panel": "^9.0.68-rc.3",
16
- "@praxisui/table-rule-builder": "^9.0.68-rc.3",
9
+ "@praxisui/ai": "^10.0.0-rc.3",
10
+ "@praxisui/core": "^10.0.0-rc.3",
11
+ "@praxisui/dynamic-fields": "^10.0.0-rc.3",
12
+ "@praxisui/dynamic-form": "^10.0.0-rc.3",
13
+ "@praxisui/metadata-editor": "^10.0.0-rc.3",
14
+ "@praxisui/rich-content": "^10.0.0-rc.3",
15
+ "@praxisui/settings-panel": "^10.0.0-rc.3",
16
+ "@praxisui/table-rule-builder": "^10.0.0-rc.3",
17
17
  "@angular/cdk": "^21.0.0",
18
18
  "@angular/forms": "^21.0.0",
19
19
  "@angular/material": "^21.0.0",
20
20
  "@angular/router": "^21.0.0",
21
- "@praxisui/dialog": "^9.0.68-rc.3",
21
+ "@praxisui/dialog": "^10.0.0-rc.3",
22
22
  "rxjs": "~7.8.0"
23
23
  },
24
24
  "dependencies": {
@@ -128,6 +128,9 @@ Este documento e a referencia canonica da API JSON de praxis-table.
128
128
  - Renderers interativos como `button`, `toggle`, `menu`, `link`, `html` e `rating`, alem do shell de detail/expansion, continuam table-owned e fora do contrato compartilhado `1.0` ate promocao semantica explicita.
129
129
 
130
130
  ## Detail rich surfaces
131
+ - `richContent` incorpora um documento canônico `praxis.rich-content@1.0.0` no corpo do registro selecionado. Use-o para `callout`, cartões semânticos, ícones, hierarquia tipográfica e ações sem duplicar essa taxonomia dentro de Table.
132
+ - O documento é validado integralmente antes do render. Cada `actionId` do conteúdo rico precisa existir em `actions.row.actions[]`; referências não declaradas ficam indisponíveis e não são despachadas. Ações declaradas são mediadas pelo host e seguem `onRowAction`; confirmação, capabilities e autorização continuam governadas pela Table e pelo backend.
133
+ - O editor visual de Detalhes delega `richContent.document` ao `PraxisRichContentConfigEditor`, incluindo tons `neutral|info|success|warning|danger`, bindings como `row.note`, mídia e botões. Tokens semânticos são o caminho recomendado; gradientes são estilo avançado e exigem prova de contraste nos temas suportados.
131
134
  - `actionBar` entra na mesma fronteira canônica de detail row para agrupar ações contextuais host-mediated.
132
135
  - `actionBar` é host-mediated:
133
136
  - o host resolve visibilidade, disabled e dispatch
@@ -138,7 +141,7 @@ Este documento e a referencia canonica da API JSON de praxis-table.
138
141
  - cada entrada usa `itemSchema` para mapear `title`, `subtitle`, `meta`, `icon` e `badge`
139
142
  - o host resolve dados e fallback, mas o rendering cronologico final fica no `PraxisRichContent`
140
143
 
141
- - `behavior.expansion.detail.schemaContract.allowedNodes` inclui `detailList` e `cardGrid` como surfaces canônicas de detail row.
144
+ - `behavior.detail.schemaContract.allowedNodes` inclui `detailList` e `cardGrid` como surfaces canônicas de detail row.
142
145
  - `list` continua sendo lista simples e nao aceita subtree declarativa por item.
143
146
  - `mediaBlock` tambem faz parte da fronteira canonica do detail row, como primitive compartilhada para avatar/imagem, headline, subtitle, meta e trailing leve.
144
147
  - `detailList` e host-mediated:
@@ -312,12 +315,12 @@ type TableAuthoringDocument = {
312
315
 
313
316
  | Path | Enablement (flag/guard) | Stability | Rollout notes | Notes |
314
317
  | --- | --- | --- | --- | --- |
315
- | `behavior.expansion.detail.source.resourcePath` | `resourceAllowList` + `schemaContract` + renderer contract | Partial | Guard rails ativos; requer evidência de host para produção | Fluxo com fail-closed quando contrato/allowlist falha. |
316
- | `behavior.expansion.detail.source.hypermedia` | `_links.capabilities` + `schemaContract` + renderer contract | Partial | Usa discovery canônico do backend; fail-closed sem `rel="capabilities"` | Primeiro corte gera detail schema leve a partir do snapshot agregado. |
318
+ | `behavior.detail.source.resourcePath` | `resourceAllowList` + `schemaContract` + renderer contract | Partial | Guard rails ativos; requer evidência de host para produção | Fluxo com fail-closed quando contrato/allowlist falha. |
319
+ | `behavior.detail.source.hypermedia` | `_links.capabilities` + `schemaContract` + renderer contract | Partial | Usa discovery canônico do backend; fail-closed sem `rel="capabilities"` | Primeiro corte gera detail schema leve a partir do snapshot agregado. |
317
320
 
318
321
  ### Hypermedia detail semantics
319
322
 
320
- - `behavior.expansion.detail.source.mode = "hypermedia"` começa sempre em `_links.capabilities`.
323
+ - `behavior.detail.source.mode = "hypermedia"` começa sempre em `_links.capabilities`.
321
324
  - `surfaces`, `actions` e `canonicalOperations` são lidos do `ResourceCapabilitySnapshot` retornado pelo backend.
322
325
  - O primeiro corte monta um detail schema leve de resumo contextual; ele não embute execução inline de `surface.open` nem de workflow.
323
326
  - O runtime faz prefetch por linha somente quando existe ao menos uma ação contextual configurada para projeção inline (`display="icons"|"buttons"`). Ações restritas ao menu preservam discovery sob demanda ao abrir o overflow; expansion `hypermedia` sem row actions continua resolvendo o contexto ao expandir a linha.
@@ -556,11 +559,11 @@ degraded filter.
556
559
 
557
560
  - input explícito de runtime tem precedência sobre persistência local.
558
561
  - paths canônicos têm precedência sobre aliases internos remanescentes (`__forceRemoteMode__`).
559
- - em `behavior.expansion.detail`, contrato inválido aplica fail-closed para detail row.
560
- - `behavior.expansion.detail.source.mode = "hypermedia"` usa `_links.capabilities` como ponto único de entrada e não executa `surface.open` inline no primeiro corte.
562
+ - em `behavior.detail`, contrato inválido aplica fail-closed para detail row.
563
+ - `behavior.detail.source.mode = "hypermedia"` usa `_links.capabilities` como ponto único de entrada e não executa `surface.open` inline no primeiro corte.
561
564
 
562
565
  Observação adicional:
563
- - no primeiro corte, `behavior.expansion.detail.source.mode = "hypermedia"` usa `_links.capabilities` como ponto único de entrada, consome `surfaces/actions/canonicalOperations` do snapshot agregado e não executa `surface.open` inline.
566
+ - no primeiro corte, `behavior.detail.source.mode = "hypermedia"` usa `_links.capabilities` como ponto único de entrada, consome `surfaces/actions/canonicalOperations` do snapshot agregado e não executa `surface.open` inline.
564
567
 
565
568
  ## Validation and error semantics
566
569
 
@@ -570,9 +573,9 @@ Observação adicional:
570
573
  | --- | --- | --- | --- | --- |
571
574
  | `tableId` para persistência | init/runtime | warn + disable persistence | `praxis-table:missing-table-id` | Tabela segue funcional sem persistir preferências. |
572
575
  | `appearance.responsive.breakpoints.mobile` | runtime normalization | fallback para `768` | `praxis-table:responsive-breakpoint-mobile-invalid` | Comportamento fail-open com warning deduplicado. |
573
- | `behavior.expansion.detail.schemaContract.kind/version` | runtime validation | fail-closed (sem render de detail) | `praxis-table:expansion:detail:schema-contract-kind-version-invalid` | Bloqueia detail schema inválido. |
574
- | `behavior.expansion.detail.source.resourcePath` allowlist | runtime validation | fail-closed | `praxis-table:expansion:detail:resource-path-not-allowlisted` | Bloqueia path fora de allowlist/URL absoluta. |
575
- | `behavior.expansion.detail.source.hypermedia` sem `_links.capabilities` | runtime validation | fail-closed | `praxis-table:expansion:detail:hypermedia-links-missing` | Bloqueia detail hypermedia quando o item não expõe affordance canônica. |
576
+ | `behavior.detail.schemaContract.kind/version` | runtime validation | fail-closed (sem render de detail) | `praxis-table:expansion:detail:schema-contract-kind-version-invalid` | Bloqueia detail schema inválido. |
577
+ | `behavior.detail.source.resourcePath` policy | canonical URL + same-origin pathname allowlist | fail-closed | `praxis-table:expansion:detail:resource-path-policy-blocked:*` | Bloqueia URL absoluta, origem divergente, traversal/representações ambíguas, path efetivo fora da allowlist e redirects. Usa credenciais same-origin e `EnterpriseRuntimeContextService.effectiveRequestHeaders()`. A allowlist protege o documento; autorização GET/POST continua no backend. Hosts dependentes de interceptors Angular devem usar o resolver governado de `source.mode=resource` ou configurar os headers canônicos. |
578
+ | `behavior.detail.source.hypermedia` sem `_links.capabilities` | runtime validation | fail-closed | `praxis-table:expansion:detail:hypermedia-links-missing` | Bloqueia detail hypermedia quando o item não expõe affordance canônica. |
576
579
  | `detail rendering contract` | runtime validation | fail-closed | `praxis-table:expansion:detail:rendering-invalid` | Exige estratégia/registry consistentes. |
577
580
 
578
581
  ### Error semantics
@@ -1462,7 +1465,19 @@ Nota: exemplos especificos do componente foram preservados na secao detalhada pa
1462
1465
 
1463
1466
  ## Governed embeds
1464
1467
 
1465
- - `behavior.expansion.detail.schemaContract.allowedNodes` agora tambem pode incluir `formRef`, `tableRef`, `chartRef`, `templateRef` e `diagramEmbed`.
1468
+ ### Contextual detail presentation
1469
+
1470
+ `behavior.detail` owns the shared schema, source, rendering, height and lazy-load configuration. `presentation.placement` selects `row` (the default) or `bottom`; `presentation.initiallyCollapsed` sets the initial disclosure state. For bottom presentation, `presentation.bottomStackPosition` selects `afterControls` (the default) or `beforeControls`, and `presentation.emptyBehavior` selects an instructional `message` (the default) or `hide`. A missing `height` defaults to dynamic sizing. `height.mode` accepts explicit `dynamic` or `fixed`; fixed mode requires a positive `px`. `behavior.expansion` owns row interaction only. Do not store detail inside expansion: the finite migration moves that branch and rejects differing old/new definitions. Runtime does not read the old path.
1471
+
1472
+ Bottom detail uses the existing selection model. Exactly one visible record with a stable identity may provide the body. Zero or multiple selections retain an explicit empty/status region; a retained selection outside the current page never reads a detail body. Refreshing the same ID refreshes its context. Selection never executes a business action.
1473
+
1474
+ Use `detail.presentation.configure` to choose bottom: it disables row expansion and enables single selection when selection is disabled, preserving an already enabled multiple-selection policy. Choosing row enables row expansion; disabling detail disables expansion. Conflicting hand-authored configurations fail closed. `detail.configure` and `expansion.configure` apply their declared activation semantics. `detail.source.configure` changes only the source; extension properties inside that source never act as presentation commands. Unknown extensions remain preserved, while malformed known groups, booleans and source modes block Apply. An existing dynamic height requires an explicit positive fixed-height adjustment before choosing bottom.
1475
+
1476
+ The Details section edits the authored tree and preserves field expressions, unknown nodes and provider references. Its local preview does not perform remote reads or persist sample values. Invalid advanced JSON blocks Apply/Save. Discard restores detail edits; global defaults retain their existing reset semantics.
1477
+
1478
+ The bottom body defaults to dynamic height with a small-viewport CSS limit. Fixed mode starts at 192px in the editor and provides vertical scrolling. It is outside the virtual viewport and defaults to after the footer controls, preserving the collection stack. Explicit collapse persists across selection changes. Inline charts require the Charts provider; unresolved references remain explained placeholders.
1479
+
1480
+ - `behavior.detail.schemaContract.allowedNodes` agora tambem pode incluir `formRef`, `tableRef`, `chartRef`, `templateRef` e `diagramEmbed`.
1466
1481
  - Esses nodes continuam host-mediated:
1467
1482
  - o host resolve discovery, registry, abertura e policy
1468
1483
  - a tabela padroniza o shell, os metadados e a CTA do embed
@@ -1542,3 +1557,4 @@ The embedded table supplies the heading, advanced-action label, dialog title and
1542
1557
  Tokens project to CSS custom properties `--pfx-filter-gap`, `--pfx-filter-header-gap`, `--pfx-filter-header-color`, `--pfx-filter-header-font-size`, `--pfx-filter-header-font-weight`, `--pfx-filter-icon-size`, `--pfx-filter-action-gap`, `--pfx-filter-action-font-size`, and `--pfx-filter-action-font-weight`. Prefer the semantic size/position controls for ordinary authoring; tokens are for deliberate theme customization.
1543
1558
 
1544
1559
  AI authoring extends existing operations: `filter.advanced.configure` receives `settings.presentation` for tables; `filter.settings.configure` receives `presentation` for standalone filters. Neither operation authors a query through this object.
1560
+ Corporate context changes use the existing `EnterpriseRuntimeContextService`: Table invalidates rows, selection, discovery and pending data/detail responses before a new remote load. Local hosts must replace `data` for the effective context and discard their own obsolete asynchronous deliveries. This is runtime state isolation, not backend authorization. `initiallyCollapsed` is reapplied after persisted hydration and configuration Apply.