@praxisui/table 8.0.0-beta.2 → 8.0.0-beta.20

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.
Files changed (37) hide show
  1. package/README.md +81 -8
  2. package/docs/DSL-Extensions-Guide.md +23 -0
  3. package/docs/adr/2026-03-dynamic-filter-cross-lib-coupling.md +107 -0
  4. package/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md +105 -0
  5. package/docs/adr/2026-03-table-editor-idfield-decision.md +85 -0
  6. package/docs/column-resize-reorder-implementation-plan.md +338 -0
  7. package/docs/column-resize-reorder-review-prompt.md +34 -0
  8. package/docs/dynamic-filter-architecture-overview.md +207 -0
  9. package/docs/dynamic-filter-backend-contract-cheatsheet.md +167 -0
  10. package/docs/dynamic-filter-editor-settings-guide.md +229 -0
  11. package/docs/dynamic-filter-host-integration-guide.md +217 -0
  12. package/docs/dynamic-filter-payload-contract.md +331 -0
  13. package/docs/dynamic-filter-range-filters-guide.md +289 -0
  14. package/docs/dynamic-filter-troubleshooting-guide.md +220 -0
  15. package/docs/dynamic-inline-filter-catalog.md +147 -0
  16. package/docs/e2e-column-drag-playwright.md +62 -0
  17. package/docs/expandable-rows-enterprise-big-leagues-plan.md +1080 -0
  18. package/docs/json-logic-operators-and-helpers.md +57 -0
  19. package/docs/local-data-mode-precedence.md +12 -0
  20. package/docs/local-data-pre-implementation-baseline.md +22 -0
  21. package/docs/local-data-preimplementation-go-no-go.md +39 -0
  22. package/docs/local-data-support-implementation-plan.md +524 -0
  23. package/docs/local-data-support-pr-package.md +66 -0
  24. package/docs/localization-persistence-merge.md +22 -0
  25. package/docs/performance-hardening-v2-implementation-plan.md +479 -0
  26. package/docs/playground-scenario-curation-plan.md +482 -0
  27. package/docs/playground-scenario-second-opinion-prompt.md +121 -0
  28. package/docs/playground-scenario-second-opinion-review.md +234 -0
  29. package/docs/release-notes-p1-hardening.md +76 -0
  30. package/docs/table-authoring-document-completeness-checklist.md +120 -0
  31. package/docs/table-editor-capability-review-prompt.md +349 -0
  32. package/docs/visual-rules-editor-transition.md +29 -0
  33. package/fesm2022/{praxisui-table-table-ai.adapter-DxjDaQqy.mjs → praxisui-table-table-ai.adapter-fS74fZ7o.mjs} +14 -5
  34. package/fesm2022/praxisui-table.mjs +3650 -324
  35. package/index.d.ts +120 -51
  36. package/package.json +15 -9
  37. package/src/lib/praxis-table.json-api.md +1315 -0
@@ -0,0 +1,349 @@
1
+ # Prompt Para Revisão Especializada: `tableEditorCapability`
2
+
3
+ ## Contexto
4
+
5
+ Estamos evoluindo a arquitetura de edição de configuração dos componentes do ecossistema Praxis UI, com foco inicial em `praxis-table`, mas com intenção clara de estabelecer um padrão reaproveitável por `praxis-list`, `praxis-dynamic-form` e futuros componentes editáveis do playground.
6
+
7
+ O problema atual não é falta de editor JSON nem falta de editor visual. O problema é ausência de um protocolo canônico único entre as diferentes superfícies de autoria e o runtime real.
8
+
9
+ Hoje convivem, de forma parcialmente desconectada:
10
+
11
+ - editor visual embutido no componente
12
+ - editor JSON embutido no componente
13
+ - playground com apply simplificado
14
+ - apply por `@Input()`
15
+ - alguns fluxos com métodos públicos como `applyConfigFromAdapter(...)`
16
+
17
+ No caso de `praxis-table`, a situação é especialmente instrutiva:
18
+
19
+ - a tabela já possui um editor robusto
20
+ - o editor não trata o JSON como `TableConfig` cru
21
+ - ele usa `editedConfig`, dirty state, normalização, coerção por modo efetivo e reconciliação de campos auxiliares
22
+ - `resourcePath`, `idField` e `horizontalScroll` vivem fora do `TableConfig` puro
23
+ - o host/runtime reinterpreta campos internos como `__resourcePath__`, `__resourcePathIntent__`, `__idField__`, `__horizontalScroll__`
24
+
25
+ Ou seja: o componente já demonstra, na prática, que o modelo correto não é "editar JSON e repassar por input". O modelo correto é "editar um documento canônico de autoria e aplicar por um protocolo oficial".
26
+
27
+ ## Motivação
28
+
29
+ Queremos transformar edição de configuração em uma capability formal do componente.
30
+
31
+ Objetivos centrais:
32
+
33
+ - round-trip confiável entre editor visual, editor JSON, playground e runtime
34
+ - separação clara entre `config` do componente e `hostInputs/contexto`
35
+ - normalização e validação centralizadas
36
+ - remoção de hacks específicos do playground
37
+ - remoção gradual de marcadores mágicos públicos como `__resourcePath__`
38
+ - base uniforme para consumo futuro por IA
39
+
40
+ O `praxis-table` será o blueprint inicial.
41
+
42
+ ## Diagnóstico resumido do estado atual em `praxis-table`
43
+
44
+ ### Editor
45
+
46
+ O editor atual concentra lógica relevante em:
47
+
48
+ - normalização de `TableConfig`
49
+ - dirty state comparando config normalizada + host inputs paralelos
50
+ - coerção de `pagination.strategy` e `sorting.strategy` para `client` em modo local
51
+ - reconciliação/preservação de `advancedFilters.settings`
52
+ - reconciliação visual de divergência com `serverIdField` e `serverSchemaHash`
53
+
54
+ ### Runtime
55
+
56
+ O host (`PraxisTable`) hoje:
57
+
58
+ - abre o editor com `tableConfig`, `resourcePath`, `idField`, `horizontalScroll`, contexto CRUD e metadados de servidor
59
+ - recebe payload de volta
60
+ - lê marcadores internos
61
+ - reconcilia `resourcePath`, `idField`, `horizontalScroll`
62
+ - injeta metadados em `config.meta`
63
+ - remove marcadores internos
64
+ - finalmente chama `applyTableConfig(...)`
65
+
66
+ Esse fluxo funciona, mas o contrato entre editor e runtime é implícito, frágil e difícil de reutilizar no playground.
67
+
68
+ ## Proposta arquitetural
69
+
70
+ Introduzir uma capability formal por componente, começando por `praxis-table`.
71
+
72
+ ### Contrato base esperado
73
+
74
+ ```ts
75
+ export interface EditorDiagnostic {
76
+ level: 'error' | 'warning' | 'info';
77
+ code: string;
78
+ message: string;
79
+ path?: string;
80
+ }
81
+
82
+ export interface ComponentEditorCapability<TDocument, TConfig, TTarget = unknown> {
83
+ kind: string;
84
+ version: 1;
85
+
86
+ createDocument(source: {
87
+ config?: unknown;
88
+ hostInputs?: Record<string, unknown>;
89
+ hostContext?: Record<string, unknown>;
90
+ }): TDocument;
91
+
92
+ normalizeDocument(raw: unknown): TDocument;
93
+ validateDocument(doc: TDocument): EditorDiagnostic[];
94
+
95
+ parseDocument(json: unknown): TDocument;
96
+ serializeDocument(doc: TDocument): unknown;
97
+
98
+ toCanonicalConfig(doc: TDocument): TConfig;
99
+
100
+ applyDocument(
101
+ target: TTarget,
102
+ doc: TDocument,
103
+ context?: unknown,
104
+ ): void | Promise<void>;
105
+ }
106
+ ```
107
+
108
+ ### Documento canônico proposto para tabela
109
+
110
+ ```ts
111
+ export type TableHorizontalScroll = 'auto' | 'wrap' | 'none';
112
+ export type ResourcePathIntent = 'set' | 'clear' | 'unchanged';
113
+ export type EffectiveDataMode = 'remote' | 'local' | 'empty';
114
+
115
+ export interface TableEditorHostInputs {
116
+ resourcePath?: string;
117
+ idField?: string;
118
+ horizontalScroll?: TableHorizontalScroll;
119
+ }
120
+
121
+ export interface TableEditorHostContext {
122
+ hasLocalDataInput?: boolean;
123
+ localDataModeFlagEnabled?: boolean;
124
+ serverIdField?: string;
125
+ serverSchemaHash?: string;
126
+ crudContext?: {
127
+ tableId: string;
128
+ componentKeyId?: string;
129
+ resourcePath?: string;
130
+ idField?: string;
131
+ };
132
+ }
133
+
134
+ export interface TableEditorMeta {
135
+ effectiveDataMode?: EffectiveDataMode;
136
+ resourcePathIntent?: ResourcePathIntent;
137
+ }
138
+
139
+ export interface TableEditorDocument {
140
+ config: TableConfig;
141
+ hostInputs?: TableEditorHostInputs;
142
+ hostContext?: TableEditorHostContext;
143
+ editorMeta?: TableEditorMeta;
144
+ }
145
+ ```
146
+
147
+ ## Plano proposto para `tableEditorCapability`
148
+
149
+ ### 1. `createDocument(source)`
150
+
151
+ Responsabilidade:
152
+
153
+ - criar o documento inicial a partir do estado real do host/editor
154
+ - derivar `resourcePath`, `idField`, `horizontalScroll`
155
+ - normalizar config de entrada
156
+ - preencher `editorMeta.effectiveDataMode`
157
+
158
+ Origem da lógica:
159
+
160
+ - `PraxisTable.openConfigEditor(...)`
161
+ - inicialização de `PraxisTableConfigEditor.ngOnInit()`
162
+
163
+ ### 2. `normalizeDocument(raw)`
164
+
165
+ Responsabilidade:
166
+
167
+ - aceitar payload novo ou legado
168
+ - migrar `__resourcePath__`, `__idField__`, `__horizontalScroll__`, `__resourcePathIntent__`
169
+ - normalizar `config`
170
+ - normalizar `hostInputs`
171
+ - derivar `effectiveDataMode`
172
+ - aplicar coerções de estratégia em modo local
173
+ - estabilizar settings de filtros avançados
174
+
175
+ Essa é a peça principal da capability.
176
+
177
+ ### 3. `validateDocument(doc)`
178
+
179
+ Responsabilidade:
180
+
181
+ - centralizar erros bloqueantes e warnings
182
+ - impedir apply inválido
183
+ - expor diagnósticos para editor visual, JSON editor e playground
184
+
185
+ Validações esperadas:
186
+
187
+ - `config.columns` deve ser array
188
+ - colunas devem ter `field`
189
+ - `horizontalScroll` deve estar no enum
190
+ - `resourcePathIntent=set` exige `resourcePath`
191
+ - `server pagination/sorting` não podem permanecer em modo local
192
+ - warning de divergência entre `hostInputs.idField` e `serverIdField`
193
+ - warning de divergência entre `config.meta.serverHash` e `serverSchemaHash`
194
+
195
+ ### 4. `toCanonicalConfig(doc)`
196
+
197
+ Responsabilidade:
198
+
199
+ - projetar somente o `TableConfig` persistível/consumível pelo runtime
200
+ - não embutir `resourcePath` nem `horizontalScroll`
201
+ - opcionalmente persistir `meta.idField`
202
+ - nunca vazar marcadores internos
203
+
204
+ ### 5. `serializeDocument(doc)` / `parseDocument(json)`
205
+
206
+ Responsabilidade:
207
+
208
+ - fazer do `TableEditorDocument` o JSON oficial de autoria
209
+ - permitir round-trip confiável entre editor visual e editor JSON
210
+ - aceitar payload legado na leitura, mas serializar só no formato novo
211
+
212
+ ### 6. `applyDocument(target, doc, context?)`
213
+
214
+ Responsabilidade:
215
+
216
+ - encapsular o fluxo hoje espalhado no `PraxisTable`
217
+ - aplicar `resourcePath`, `idField`, `horizontalScroll`
218
+ - persistir inputs quando necessário
219
+ - compor `config.meta`
220
+ - persistir config quando necessário
221
+ - chamar o apply final do runtime
222
+
223
+ Contexto sugerido:
224
+
225
+ ```ts
226
+ export interface TableApplyContext {
227
+ trigger: 'applied' | 'saved' | 'adapter' | 'playground';
228
+ persistConfig?: boolean;
229
+ persistInputs?: boolean;
230
+ }
231
+ ```
232
+
233
+ ## Como isso substituiria o fluxo atual
234
+
235
+ ### Hoje
236
+
237
+ O editor devolve algo próximo de `TableConfig`, mas injeta campos internos:
238
+
239
+ - `__resourcePath__`
240
+ - `__resourcePathIntent__`
241
+ - `__idField__`
242
+ - `__horizontalScroll__`
243
+
244
+ O host reinterpreta isso manualmente.
245
+
246
+ ### Proposto
247
+
248
+ O editor devolve `TableEditorDocument`.
249
+
250
+ O host faz:
251
+
252
+ ```ts
253
+ const doc = tableEditorCapability.parseDocument(value);
254
+ tableEditorCapability.applyDocument(this, doc, {
255
+ trigger: 'saved',
256
+ persistConfig: true,
257
+ persistInputs: true,
258
+ });
259
+ ```
260
+
261
+ ## Compatibilidade
262
+
263
+ Queremos migração incremental, sem quebra abrupta.
264
+
265
+ Estratégia:
266
+
267
+ 1. capability nova aceita payload legado
268
+ 2. editor passa a produzir `TableEditorDocument`
269
+ 3. runtime passa a preferir capability
270
+ 4. fallback legado de `__...__` permanece temporariamente
271
+ 5. playground passa a consumir capability
272
+ 6. só depois removemos o protocolo mágico
273
+
274
+ ## O que eu quero da revisão especializada
275
+
276
+ Quero uma revisão técnica rigorosa do desenho do `tableEditorCapability`, com foco em:
277
+
278
+ ### 1. Contrato
279
+
280
+ - o `TableEditorDocument` está bem delimitado?
281
+ - `hostInputs`, `hostContext` e `editorMeta` estão bem separados?
282
+ - há campos demais ou de menos no documento?
283
+
284
+ ### 2. Normalização
285
+
286
+ - a responsabilidade de `normalizeDocument()` está correta?
287
+ - alguma parte importante do comportamento atual da tabela ficaria fora?
288
+ - há risco de normalização com efeitos colaterais excessivos?
289
+
290
+ ### 3. Apply
291
+
292
+ - `applyDocument()` deve chamar diretamente `applyTableConfig(...)`?
293
+ - a composição de `meta.idField`, `meta.version`, `meta.updatedAt`, `schemaId`, `serverHash` está no lugar certo?
294
+ - a persistência de `horizontalScroll` e `resourcePath` deveria ficar no capability ou no host?
295
+
296
+ ### 4. Boundary público
297
+
298
+ - faz sentido expor `applyDocument()` como API oficial do componente?
299
+ - `toCanonicalConfig()` deve persistir `meta.idField` ou isso deve ser decisão só do host?
300
+ - `serverIdField` e `serverSchemaHash` devem existir no documento serializado ou apenas no contexto de sessão?
301
+
302
+ ### 5. Migração
303
+
304
+ - a estratégia de compatibilidade com `__resourcePath__` etc. está adequada?
305
+ - existe uma abordagem melhor para migrar sem quebrar playground/editor atual?
306
+
307
+ ### 6. Riscos
308
+
309
+ - riscos de drift que ainda permaneceriam
310
+ - riscos de acoplamento excessivo entre capability e classe Angular do componente
311
+ - riscos de versionamento do documento
312
+
313
+ ## Critério de qualidade da revisão
314
+
315
+ Prefiro uma revisão em modo crítico, não superficial.
316
+
317
+ Se você enxergar fragilidade conceitual, ponto cego arquitetural, boundary errado ou risco de manutenção, aponte diretamente.
318
+
319
+ Quero principalmente saber:
320
+
321
+ - onde esse design ainda está fraco
322
+ - o que deveria ser movido de lugar
323
+ - o que ainda está dependente demais do estado atual do componente
324
+ - como deixar isso forte o suficiente para virar padrão do ecossistema
325
+
326
+ ## Referências úteis no código atual
327
+
328
+ - `projects/praxis-table/src/lib/praxis-table-config-editor.ts`
329
+ - `projects/praxis-table/src/lib/praxis-table.ts`
330
+ - `projects/praxis-table/src/lib/json-config-editor/json-config-editor.component.ts`
331
+
332
+ Pontos mais relevantes observados no código atual:
333
+
334
+ - normalização/editor state no `PraxisTableConfigEditor`
335
+ - dirty state com `resourcePath`, `idField`, `horizontalScroll`
336
+ - coerção em modo local
337
+ - markers `__resourcePath__`, `__resourcePathIntent__`, `__idField__`, `__horizontalScroll__`
338
+ - apply final no runtime via `applyTableConfig(...)`
339
+
340
+ ## Resultado esperado da revisão
341
+
342
+ Quero uma devolutiva estruturada contendo:
343
+
344
+ 1. avaliação geral do desenho
345
+ 2. falhas ou riscos mais importantes
346
+ 3. mudanças recomendadas no contrato
347
+ 4. mudanças recomendadas na estratégia de apply
348
+ 5. recomendações de rollout/migração
349
+ 6. se possível, uma proposta refinada do shape final da capability
@@ -0,0 +1,29 @@
1
+ # Transição: Editor de Regras da Tabela (especializado)
2
+
3
+ Status: concluído (novo editor disponível)
4
+
5
+ Resumo
6
+ - A aba "Regras Visuais" foi removida do editor de configuração da Tabela (`PraxisTableConfigEditor`).
7
+ - O wrapper anterior baseado no construtor genérico visual foi descontinuado nesta biblioteca.
8
+ - Um editor especializado de regras da Tabela foi introduzido e substitui o fluxo anterior.
9
+
10
+ Motivação
11
+ - Reduzir complexidade e dependências desnecessárias do builder genérico.
12
+ - Focar o domínio de Tabela (alvos linha/célula, efeitos dedicados e integração direta com `TableConfig`).
13
+
14
+ Impacto
15
+ - A aba "Regras" agora utiliza o novo editor especializado, com fluxo column‑first, operadores por tipo, editores de valor dinâmicos e construtor de grupos (AND/OR/NOT).
16
+ - As regras continuam salvas como DSL em `rowConditionalStyles` e `columns[].conditionalStyles` (runtime inalterado).
17
+ - O runtime DSL da tabela foi ampliado com helpers corporativos embutidos (`jsonType`, `eqIgnoreCase`, `between`, `dateBetween`, `containsAny`, `containsAll`, `coalesce`), sem necessidade de registro manual no host.
18
+
19
+ Alternativas
20
+ - A aba JSON permanece disponível para ajustes diretos quando necessário.
21
+
22
+ Notas técnicas
23
+ - Componentes e conversores removidos (nomes antigos omitidos por política):
24
+ - Editor visual anterior e seu wrapper
25
+ - Conversores de regras do editor visual e seus testes
26
+ - Remoções de export na API pública: `src/public-api.ts`.
27
+
28
+ Próximos passos
29
+ - Evoluir efeitos dedicados (classe/estilo/ícone/imagem/badge/valor/tooltip) preservando compatibilidade de runtime.
@@ -198,11 +198,12 @@ class TableAiAdapter extends BaseAiAdapter {
198
198
  const actions = config.actions || {};
199
199
  const availableFeatures = [];
200
200
  const missingCapabilities = [];
201
+ const effectiveIdField = this.normalizeString(this.table.getIdField?.());
201
202
  if (!this.table.resourcePath) {
202
203
  availableFeatures.push('data-connection');
203
204
  }
204
- if (!this.table.idField) {
205
- availableFeatures.push('bindings.idField');
205
+ if (!effectiveIdField) {
206
+ availableFeatures.push('meta.idField');
206
207
  }
207
208
  if (!behavior.filtering?.enabled) {
208
209
  availableFeatures.push('behavior.filtering');
@@ -264,14 +265,15 @@ class TableAiAdapter extends BaseAiAdapter {
264
265
  authoringContract: {
265
266
  kind: 'praxis.table.editor',
266
267
  usesBindings: true,
267
- bindingsPaths: ['bindings.resourcePath', 'bindings.idField', 'bindings.horizontalScroll'],
268
+ bindingsPaths: ['bindings.resourcePath', 'bindings.horizontalScroll'],
269
+ configPaths: ['meta.idField'],
268
270
  runtimeConfigProjection: 'TableConfig',
269
271
  },
270
272
  availableFeatures,
271
273
  missingCapabilities: Array.from(new Set(missingCapabilities)),
272
274
  inputs: {
273
275
  resourcePath: this.table.resourcePath || null,
274
- idField: this.table.getIdField?.() || null,
276
+ idField: effectiveIdField || null,
275
277
  horizontalScroll: this.table.horizontalScroll || null,
276
278
  },
277
279
  };
@@ -303,6 +305,13 @@ class TableAiAdapter extends BaseAiAdapter {
303
305
  this.applyConfig(nextConfig);
304
306
  return { success: true };
305
307
  }
308
+ normalizeString(value) {
309
+ if (typeof value !== 'string') {
310
+ return null;
311
+ }
312
+ const normalized = value.trim();
313
+ return normalized ? normalized : null;
314
+ }
306
315
  // -------- Context & suggestions --------
307
316
  /**
308
317
  * Human-friendly summary for prompt/context (columns + feature flags + data stats).
@@ -564,7 +573,7 @@ Columns Analysis:
564
573
  const id = this.table.tableId || 'default';
565
574
  const rp = this.table.resourcePath || 'default';
566
575
  // bump version to invalidate old cached suggestions
567
- return `ai-suggestions:v3:${id}:${rp}`;
576
+ return `ai-suggestions:v4:${id}:${rp}`;
568
577
  }
569
578
  getColumnNames() {
570
579
  return (this.table.config?.columns || [])