@praxisui/table 1.0.0-beta.7 → 1.0.0-beta.8

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.
@@ -3285,15 +3285,17 @@ class DataFormattingService {
3285
3285
  * Format currency values
3286
3286
  */
3287
3287
  formatCurrency(value, formatString) {
3288
- // Parse format: "BRL|symbol|2" or "USD|code|2"
3289
- const parts = formatString.split('|');
3290
- if (parts.length < 3) {
3291
- return (this.currencyPipe.transform(value, 'BRL', 'symbol', '1.2-2', this.locale) || value.toString());
3292
- }
3293
- const currencyCode = parts[0];
3294
- const display = parts[1]; // 'symbol' or 'code'
3295
- const decimals = parts[2];
3288
+ // Accept both compact and detailed formats:
3289
+ // - "BRL" → code only (defaults: symbol, 2 decimals)
3290
+ // - "USD|code|0" code + display + decimals
3291
+ // - "EUR|symbol|2|nosep" with grouping removal
3292
+ const parts = (formatString || '').split('|').filter((p) => p != null && p !== '');
3293
+ const currencyCode = (parts[0] || 'BRL').trim();
3294
+ const displayRaw = (parts[1] || '').trim();
3295
+ const decimalsRaw = (parts[2] || '').trim();
3296
3296
  const noSep = parts.includes('nosep');
3297
+ const display = displayRaw === 'code' ? 'code' : 'symbol';
3298
+ const decimals = /^\d+$/.test(decimalsRaw) ? decimalsRaw : '2';
3297
3299
  const digitsInfo = `1.${decimals}-${decimals}`;
3298
3300
  const formatted = this.currencyPipe.transform(value, currencyCode, display, digitsInfo, this.locale) || value.toString();
3299
3301
  return noSep ? this.removeGrouping(formatted) : formatted;
@@ -13516,7 +13518,12 @@ class TableVisualRulesEditorComponent {
13516
13518
  if (this.scope === 'row') {
13517
13519
  const anyCfg = this.config;
13518
13520
  this.selectedColumn = null;
13519
- this.currentRulesState = anyCfg._rowStyleRulesState || undefined;
13521
+ // Prefer explicit editor state; fall back to building from existing saved rules
13522
+ this.currentRulesState =
13523
+ anyCfg._rowStyleRulesState ||
13524
+ (anyCfg.rowConditionalStyles
13525
+ ? conditionalStylesToBuilderState(anyCfg.rowConditionalStyles)
13526
+ : undefined);
13520
13527
  this.compiledRules = this.materializeCompiledRules(anyCfg.rowConditionalStyles || []);
13521
13528
  if (hadPending && previousCompiled.length) {
13522
13529
  this.mergePendingIntoCompiled(previousCompiled);
@@ -13525,7 +13532,12 @@ class TableVisualRulesEditorComponent {
13525
13532
  }
13526
13533
  this.selectedColumn = this.columns.find(c => c.field === this.selectedField) || null;
13527
13534
  const anyCol = this.selectedColumn;
13528
- this.currentRulesState = anyCol?._styleRulesState || undefined;
13535
+ // Prefer explicit editor state; fall back to building from existing saved rules
13536
+ this.currentRulesState =
13537
+ anyCol?._styleRulesState ||
13538
+ (anyCol?.conditionalStyles
13539
+ ? conditionalStylesToBuilderState(anyCol.conditionalStyles)
13540
+ : undefined);
13529
13541
  this.compiledRules = this.materializeCompiledRules(anyCol?.conditionalStyles || []);
13530
13542
  if (hadPending && previousCompiled.length) {
13531
13543
  this.mergePendingIntoCompiled(previousCompiled);
@@ -13710,7 +13722,11 @@ class TableVisualRulesEditorComponent {
13710
13722
  const toPersist = this.compiledRules.map(r => ({ condition: r.condition, cssClass: r.cssClass, style: r.style }));
13711
13723
  console.debug('[TableRulesEditor] applyEffects', { scope: this.scope, toPersist });
13712
13724
  if (this.scope === 'row') {
13713
- const updated = { ...this.config, rowConditionalStyles: toPersist };
13725
+ const updated = {
13726
+ ...this.config,
13727
+ rowConditionalStyles: toPersist,
13728
+ _rowStyleRulesState: this.config._rowStyleRulesState ?? this.currentRulesState,
13729
+ };
13714
13730
  this.config = updated;
13715
13731
  this.configChange.emit(updated);
13716
13732
  console.debug('[TableRulesEditor] row effects persisted');
@@ -13722,7 +13738,11 @@ class TableVisualRulesEditorComponent {
13722
13738
  const idx = this.columns.findIndex(c => c.field === this.selectedColumn.field);
13723
13739
  if (idx < 0)
13724
13740
  return;
13725
- const col = { ...this.columns[idx], conditionalStyles: toPersist };
13741
+ const col = {
13742
+ ...this.columns[idx],
13743
+ conditionalStyles: toPersist,
13744
+ _styleRulesState: this.columns[idx]._styleRulesState ?? this.currentRulesState,
13745
+ };
13726
13746
  const newColumns = [...this.columns];
13727
13747
  newColumns[idx] = col;
13728
13748
  const updated = { ...this.config, columns: newColumns };
@@ -17292,6 +17312,7 @@ class PraxisTable {
17292
17312
  }
17293
17313
  // Cache precompilado para expressões de regras visuais (DSL → Specification)
17294
17314
  styleSpecCache = new Map();
17315
+ actionSpecCache = new Map();
17295
17316
  // Lightweight error state to expose CTA when backend/schema fails
17296
17317
  schemaError = false;
17297
17318
  dataError = false;
@@ -17540,9 +17561,22 @@ class PraxisTable {
17540
17561
  return [...actions].sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
17541
17562
  }
17542
17563
  isActionVisible(a, row) {
17543
- return typeof a.visible === 'function'
17544
- ? !!a.visible(row)
17545
- : a.visible !== false;
17564
+ // Explicit visible handler has precedence
17565
+ if (typeof a.visible === 'function')
17566
+ return !!a.visible(row);
17567
+ if (a.visible === false)
17568
+ return false;
17569
+ // Evaluate conditional (DSL) when provided
17570
+ const cond = a.conditional;
17571
+ if (cond && typeof cond === 'string' && cond.trim()) {
17572
+ try {
17573
+ return this.evaluateActionCondition(cond, row);
17574
+ }
17575
+ catch {
17576
+ return false;
17577
+ }
17578
+ }
17579
+ return true;
17546
17580
  }
17547
17581
  isActionDisabled(a, row) {
17548
17582
  return typeof a.disabled === 'function' ? !!a.disabled(row) : !!a.disabled;
@@ -18800,7 +18834,8 @@ class PraxisTable {
18800
18834
  return false;
18801
18835
  let spec = this.styleSpecCache.get(expression);
18802
18836
  if (spec === undefined) {
18803
- const knownFields = this.visibleColumns.map((c) => c.field);
18837
+ const allColumns = (this.config?.columns || this.visibleColumns || []);
18838
+ const knownFields = allColumns.map((c) => c.field);
18804
18839
  const parse = this.specBridge.parseDslExpression(expression, {
18805
18840
  knownFields,
18806
18841
  enablePerformanceWarnings: false,
@@ -18829,6 +18864,41 @@ class PraxisTable {
18829
18864
  return false;
18830
18865
  }
18831
18866
  }
18867
+ /** Evaluate row action visibility condition using the same DSL as styles */
18868
+ evaluateActionCondition(expression, rowData) {
18869
+ if (!expression || !expression.trim())
18870
+ return true;
18871
+ let spec = this.actionSpecCache.get(expression);
18872
+ if (spec === undefined) {
18873
+ const allColumns = (this.config?.columns || this.visibleColumns || []);
18874
+ const knownFields = allColumns.map((c) => c.field);
18875
+ const parse = this.specBridge.parseDslExpression(expression, {
18876
+ knownFields,
18877
+ enablePerformanceWarnings: false,
18878
+ maxComplexity: 64,
18879
+ });
18880
+ if (!parse.success || !parse.specification) {
18881
+ console.warn('[PraxisTable] Action DSL parse failed', {
18882
+ expression,
18883
+ knownFields,
18884
+ issues: parse.issues,
18885
+ });
18886
+ this.actionSpecCache.set(expression, null);
18887
+ return true; // be permissive when parse fails
18888
+ }
18889
+ spec = parse.specification;
18890
+ this.actionSpecCache.set(expression, spec);
18891
+ }
18892
+ if (!spec)
18893
+ return true;
18894
+ try {
18895
+ return spec.isSatisfiedBy(rowData) === true;
18896
+ }
18897
+ catch {
18898
+ console.warn('[PraxisTable] Action spec evaluation error', { expression });
18899
+ return true;
18900
+ }
18901
+ }
18832
18902
  // =============================
18833
18903
  // Conditional Styles (row/global)
18834
18904
  // =============================