@praxisui/table 10.0.0-rc.19 → 10.0.0-rc.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.
- package/README.md +3 -1
- package/ai/component-registry.json +2 -2
- package/fesm2022/{praxisui-table-praxisui-table-B263nnvm.mjs → praxisui-table-praxisui-table-Coph3LrY.mjs} +836 -31
- package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-BQjoJKN_.mjs → praxisui-table-table-agentic-authoring-turn-flow-LLzzZHSg.mjs} +1 -1
- package/fesm2022/{praxisui-table-table-ai.adapter-ndYth7DX.mjs → praxisui-table-table-ai.adapter-D-PEKBru.mjs} +1 -1
- package/fesm2022/praxisui-table.mjs +1 -1
- package/package.json +10 -10
- package/types/praxisui-table.d.ts +25 -1
|
@@ -9025,6 +9025,48 @@ const PRAXIS_TABLE_EDITOR_I18N_CONFIG = {
|
|
|
9025
9025
|
'columns.renderer.microVisualization.guidance.horizontalSpace': 'Condicional: visualizações de tendência precisam de largura horizontal para manter a legibilidade; confira a largura configurada da coluna.',
|
|
9026
9026
|
'columns.renderer.microVisualization.guidance.rowDensity': 'Condicional: comparison aumenta a altura da linha. Use apenas quando densidade não for um requisito principal.',
|
|
9027
9027
|
'columns.renderer.microVisualization.guidance.stepLabels': 'Condicional: processFlow exige etapas reconhecíveis. Prefira o detalhe quando os rótulos forem essenciais.',
|
|
9028
|
+
'columns.renderer.microVisualization.kind': 'Visualização',
|
|
9029
|
+
'columns.renderer.microVisualization.kind.delta': 'Delta',
|
|
9030
|
+
'columns.renderer.microVisualization.kind.bullet': 'Bullet (meta)',
|
|
9031
|
+
'columns.renderer.microVisualization.kind.radial': 'Radial',
|
|
9032
|
+
'columns.renderer.microVisualization.kind.harveyBall': 'Harvey ball',
|
|
9033
|
+
'columns.renderer.microVisualization.kind.line': 'Linha',
|
|
9034
|
+
'columns.renderer.microVisualization.kind.area': 'Área',
|
|
9035
|
+
'columns.renderer.microVisualization.kind.column': 'Colunas',
|
|
9036
|
+
'columns.renderer.microVisualization.kind.comparison': 'Comparação',
|
|
9037
|
+
'columns.renderer.microVisualization.kind.stackedBar': 'Barra empilhada',
|
|
9038
|
+
'columns.renderer.microVisualization.kind.processFlow': 'Fluxo de processo',
|
|
9039
|
+
'columns.renderer.microVisualization.valueExpression': 'Expressão de valor',
|
|
9040
|
+
'columns.renderer.microVisualization.pointsExpression': 'Expressão de pontos',
|
|
9041
|
+
'columns.renderer.microVisualization.segmentsExpression': 'Expressão de segmentos',
|
|
9042
|
+
'columns.renderer.microVisualization.itemsExpression': 'Expressão de itens',
|
|
9043
|
+
'columns.renderer.microVisualization.totalExpression': 'Expressão de total',
|
|
9044
|
+
'columns.renderer.microVisualization.targetExpression': 'Expressão de meta',
|
|
9045
|
+
'columns.renderer.microVisualization.tone': 'Tom (cor)',
|
|
9046
|
+
'columns.renderer.microVisualization.tone.auto': 'Automático (por faixas / semântico)',
|
|
9047
|
+
'columns.renderer.microVisualization.tone.neutral': 'Neutro',
|
|
9048
|
+
'columns.renderer.microVisualization.tone.info': 'Informativo',
|
|
9049
|
+
'columns.renderer.microVisualization.tone.success': 'Sucesso',
|
|
9050
|
+
'columns.renderer.microVisualization.tone.warning': 'Alerta',
|
|
9051
|
+
'columns.renderer.microVisualization.tone.danger': 'Perigo',
|
|
9052
|
+
'columns.renderer.microVisualization.tone.critical': 'Crítico',
|
|
9053
|
+
'columns.renderer.microVisualization.tone.precedenceHint': 'No modo Automático, a cor vem das faixas de cor (thresholds) ou do sinal do valor. Um tom fixo substitui as faixas condicionais.',
|
|
9054
|
+
'columns.renderer.microVisualization.fallbackText': 'Texto alternativo acessível',
|
|
9055
|
+
'columns.renderer.microVisualization.hint': 'Use valor para indicadores, pontos para tendências, segmentos para barras empilhadas e itens para fluxos de processo. A tabela mantém o visual compacto e expõe o texto alternativo para tecnologias assistivas.',
|
|
9056
|
+
'columns.renderer.microVisualization.thresholds.title': 'Faixas de cor (thresholds)',
|
|
9057
|
+
'columns.renderer.microVisualization.thresholds.description': 'Avalia de cima para baixo (a primeira faixa compatível vence). Limites min e max são inclusivos (min <= valor <= max).',
|
|
9058
|
+
'columns.renderer.microVisualization.thresholds.add': 'Adicionar faixa',
|
|
9059
|
+
'columns.renderer.microVisualization.thresholds.preset': 'Preset semáforo (70+ / 40–69 / ≤39)',
|
|
9060
|
+
'columns.renderer.microVisualization.thresholds.min': 'Mínimo (inclusivo)',
|
|
9061
|
+
'columns.renderer.microVisualization.thresholds.max': 'Máximo (inclusivo)',
|
|
9062
|
+
'columns.renderer.microVisualization.thresholds.tone': 'Tom da faixa',
|
|
9063
|
+
'columns.renderer.microVisualization.thresholds.moveUp': 'Mover faixa para cima',
|
|
9064
|
+
'columns.renderer.microVisualization.thresholds.moveDown': 'Mover faixa para baixo',
|
|
9065
|
+
'columns.renderer.microVisualization.thresholds.remove': 'Remover faixa',
|
|
9066
|
+
'columns.renderer.microVisualization.thresholds.empty': 'Nenhuma faixa configurada. Adicione faixas ou aplique o preset semáforo para colorir automaticamente por valor.',
|
|
9067
|
+
'columns.renderer.microVisualization.thresholds.sampleValues': 'Valores de teste da prévia (separados por vírgula)',
|
|
9068
|
+
'columns.renderer.microVisualization.validation.thresholdEmptyBounds': 'Microvisualização: a faixa {index} precisa definir ao menos um limite (mínimo ou máximo).',
|
|
9069
|
+
'columns.renderer.microVisualization.validation.thresholdMinGreaterThanMax': 'Microvisualização: na faixa {index}, o mínimo ({min}) não pode ser maior que o máximo ({max}).',
|
|
9028
9070
|
},
|
|
9029
9071
|
'en-US': {
|
|
9030
9072
|
'filter.presentation.tab': 'Presentation',
|
|
@@ -10357,6 +10399,48 @@ const PRAXIS_TABLE_EDITOR_I18N_CONFIG = {
|
|
|
10357
10399
|
'columns.renderer.microVisualization.guidance.horizontalSpace': 'Conditional: trend visualizations need horizontal space to remain legible; check the configured column width.',
|
|
10358
10400
|
'columns.renderer.microVisualization.guidance.rowDensity': 'Conditional: comparison increases row height. Use it only when density is not a primary requirement.',
|
|
10359
10401
|
'columns.renderer.microVisualization.guidance.stepLabels': 'Conditional: processFlow needs recognizable steps. Prefer the detail view when labels are essential.',
|
|
10402
|
+
'columns.renderer.microVisualization.kind': 'Visualization',
|
|
10403
|
+
'columns.renderer.microVisualization.kind.delta': 'Delta',
|
|
10404
|
+
'columns.renderer.microVisualization.kind.bullet': 'Bullet',
|
|
10405
|
+
'columns.renderer.microVisualization.kind.radial': 'Radial',
|
|
10406
|
+
'columns.renderer.microVisualization.kind.harveyBall': 'Harvey ball',
|
|
10407
|
+
'columns.renderer.microVisualization.kind.line': 'Line',
|
|
10408
|
+
'columns.renderer.microVisualization.kind.area': 'Area',
|
|
10409
|
+
'columns.renderer.microVisualization.kind.column': 'Column',
|
|
10410
|
+
'columns.renderer.microVisualization.kind.comparison': 'Comparison',
|
|
10411
|
+
'columns.renderer.microVisualization.kind.stackedBar': 'Stacked bar',
|
|
10412
|
+
'columns.renderer.microVisualization.kind.processFlow': 'Process flow',
|
|
10413
|
+
'columns.renderer.microVisualization.valueExpression': 'Value expression',
|
|
10414
|
+
'columns.renderer.microVisualization.pointsExpression': 'Points expression',
|
|
10415
|
+
'columns.renderer.microVisualization.segmentsExpression': 'Segments expression',
|
|
10416
|
+
'columns.renderer.microVisualization.itemsExpression': 'Items expression',
|
|
10417
|
+
'columns.renderer.microVisualization.totalExpression': 'Total expression',
|
|
10418
|
+
'columns.renderer.microVisualization.targetExpression': 'Target expression',
|
|
10419
|
+
'columns.renderer.microVisualization.tone': 'Tone',
|
|
10420
|
+
'columns.renderer.microVisualization.tone.auto': 'Automatic (by thresholds / semantic)',
|
|
10421
|
+
'columns.renderer.microVisualization.tone.neutral': 'Neutral',
|
|
10422
|
+
'columns.renderer.microVisualization.tone.info': 'Info',
|
|
10423
|
+
'columns.renderer.microVisualization.tone.success': 'Success',
|
|
10424
|
+
'columns.renderer.microVisualization.tone.warning': 'Warning',
|
|
10425
|
+
'columns.renderer.microVisualization.tone.danger': 'Danger',
|
|
10426
|
+
'columns.renderer.microVisualization.tone.critical': 'Critical',
|
|
10427
|
+
'columns.renderer.microVisualization.tone.precedenceHint': 'In Automatic mode, color is resolved from threshold bands or value sign. A fixed tone overrides conditional bands.',
|
|
10428
|
+
'columns.renderer.microVisualization.fallbackText': 'Accessible fallback text',
|
|
10429
|
+
'columns.renderer.microVisualization.hint': 'Use a value for indicators, points for trends, segments for stacked bars, and items for process flows. The table keeps the visual compact and exposes fallback text to assistive technology.',
|
|
10430
|
+
'columns.renderer.microVisualization.thresholds.title': 'Color bands (thresholds)',
|
|
10431
|
+
'columns.renderer.microVisualization.thresholds.description': 'Evaluates top-to-bottom (first matching band wins). Both min and max bounds are inclusive (min <= value <= max).',
|
|
10432
|
+
'columns.renderer.microVisualization.thresholds.add': 'Add threshold',
|
|
10433
|
+
'columns.renderer.microVisualization.thresholds.preset': 'Traffic-light preset (70+ / 40–69 / ≤39)',
|
|
10434
|
+
'columns.renderer.microVisualization.thresholds.min': 'Min (inclusive)',
|
|
10435
|
+
'columns.renderer.microVisualization.thresholds.max': 'Max (inclusive)',
|
|
10436
|
+
'columns.renderer.microVisualization.thresholds.tone': 'Band tone',
|
|
10437
|
+
'columns.renderer.microVisualization.thresholds.moveUp': 'Move threshold up',
|
|
10438
|
+
'columns.renderer.microVisualization.thresholds.moveDown': 'Move threshold down',
|
|
10439
|
+
'columns.renderer.microVisualization.thresholds.remove': 'Remove threshold',
|
|
10440
|
+
'columns.renderer.microVisualization.thresholds.empty': 'No threshold bands configured. Add bands or apply the traffic-light preset to color values automatically.',
|
|
10441
|
+
'columns.renderer.microVisualization.thresholds.sampleValues': 'Preview sample values (comma-separated)',
|
|
10442
|
+
'columns.renderer.microVisualization.validation.thresholdEmptyBounds': 'Micro visualization: threshold {index} must define at least one bound (min or max).',
|
|
10443
|
+
'columns.renderer.microVisualization.validation.thresholdMinGreaterThanMax': 'Micro visualization: in threshold {index}, min ({min}) cannot be greater than max ({max}).',
|
|
10360
10444
|
},
|
|
10361
10445
|
},
|
|
10362
10446
|
},
|
|
@@ -23293,7 +23377,7 @@ class PraxisTable {
|
|
|
23293
23377
|
if (this.aiAdapter || this.aiAdapterLoadStarted)
|
|
23294
23378
|
return;
|
|
23295
23379
|
this.aiAdapterLoadStarted = true;
|
|
23296
|
-
import('./praxisui-table-table-ai.adapter-
|
|
23380
|
+
import('./praxisui-table-table-ai.adapter-D-PEKBru.mjs')
|
|
23297
23381
|
.then(({ TableAiAdapter }) => {
|
|
23298
23382
|
if (!this.isAiAssistantEnabled()) {
|
|
23299
23383
|
this.aiAssistantOpenAfterAdapterLoad = false;
|
|
@@ -24065,7 +24149,7 @@ class PraxisTable {
|
|
|
24065
24149
|
initializeAiAssistantController() {
|
|
24066
24150
|
if (!this.aiAdapter || this.aiAssistantController)
|
|
24067
24151
|
return;
|
|
24068
|
-
import('./praxisui-table-table-agentic-authoring-turn-flow-
|
|
24152
|
+
import('./praxisui-table-table-agentic-authoring-turn-flow-LLzzZHSg.mjs')
|
|
24069
24153
|
.then(({ TableAgenticAuthoringTurnFlow }) => {
|
|
24070
24154
|
if (this.aiAssistantController || !this.aiAdapter)
|
|
24071
24155
|
return;
|
|
@@ -45381,11 +45465,10 @@ class ColumnsConfigEditorComponent {
|
|
|
45381
45465
|
ov.renderer.type = val;
|
|
45382
45466
|
if (val === 'microVisualization') {
|
|
45383
45467
|
ov.renderer.microVisualization = ov.renderer.microVisualization || {};
|
|
45384
|
-
ov.renderer.microVisualization.visualization
|
|
45385
|
-
|
|
45386
|
-
...
|
|
45387
|
-
surface: 'table-cell'
|
|
45388
|
-
};
|
|
45468
|
+
const existing = ov.renderer.microVisualization.visualization;
|
|
45469
|
+
ov.renderer.microVisualization.visualization = existing && typeof existing === 'object'
|
|
45470
|
+
? { ...existing, surface: 'table-cell' }
|
|
45471
|
+
: { ...this.createDefaultMicroVisualization(), surface: 'table-cell' };
|
|
45389
45472
|
}
|
|
45390
45473
|
this.onColumnPropertyChange();
|
|
45391
45474
|
}
|
|
@@ -45399,20 +45482,32 @@ class ColumnsConfigEditorComponent {
|
|
|
45399
45482
|
return undefined;
|
|
45400
45483
|
}
|
|
45401
45484
|
}
|
|
45402
|
-
|
|
45485
|
+
ensureOverrideMicroVisualizationObject() {
|
|
45403
45486
|
const override = this.getConditionalOverrides()[this.condOverridesSelectedIndex];
|
|
45404
45487
|
if (!override)
|
|
45405
|
-
return;
|
|
45488
|
+
return null;
|
|
45406
45489
|
override.renderer = override.renderer || {};
|
|
45407
45490
|
override.renderer.type = 'microVisualization';
|
|
45408
45491
|
override.renderer.microVisualization = override.renderer.microVisualization || {};
|
|
45409
|
-
override.renderer.microVisualization.visualization
|
|
45410
|
-
|
|
45411
|
-
|
|
45412
|
-
|
|
45413
|
-
|
|
45414
|
-
override.renderer.microVisualization.visualization
|
|
45492
|
+
const existing = override.renderer.microVisualization.visualization;
|
|
45493
|
+
override.renderer.microVisualization.visualization =
|
|
45494
|
+
existing && typeof existing === 'object'
|
|
45495
|
+
? { ...existing, surface: 'table-cell' }
|
|
45496
|
+
: { ...this.createDefaultMicroVisualization(), surface: 'table-cell' };
|
|
45497
|
+
return override.renderer.microVisualization.visualization;
|
|
45498
|
+
}
|
|
45499
|
+
setOverrideMicroVisualizationProp(path, value) {
|
|
45500
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45501
|
+
if (!visualization)
|
|
45502
|
+
return;
|
|
45503
|
+
if (value === undefined || value === null || (path === 'tone' && value === '')) {
|
|
45504
|
+
delete visualization[path];
|
|
45505
|
+
}
|
|
45506
|
+
else {
|
|
45507
|
+
visualization[path] = value;
|
|
45508
|
+
}
|
|
45415
45509
|
this.onColumnPropertyChange();
|
|
45510
|
+
this.validateRenderer();
|
|
45416
45511
|
}
|
|
45417
45512
|
getOverrideMicroVisualizationKind() {
|
|
45418
45513
|
const kind = this.getOverrideMicroVisualizationProp('kind');
|
|
@@ -45442,6 +45537,105 @@ class ColumnsConfigEditorComponent {
|
|
|
45442
45537
|
isOverrideMicroVisualizationTotalKind() {
|
|
45443
45538
|
return ['bullet', 'radial', 'harveyBall'].includes(this.getOverrideMicroVisualizationKind());
|
|
45444
45539
|
}
|
|
45540
|
+
isOverrideMicroVisualizationThresholdsSupported() {
|
|
45541
|
+
return ['delta', 'bullet', 'radial', 'harveyBall', 'line', 'area', 'column', 'comparison'].includes(this.getOverrideMicroVisualizationKind());
|
|
45542
|
+
}
|
|
45543
|
+
getOverrideMicroVisualizationThresholds() {
|
|
45544
|
+
const thresholds = this.getOverrideMicroVisualizationProp('thresholds');
|
|
45545
|
+
return Array.isArray(thresholds) ? thresholds : [];
|
|
45546
|
+
}
|
|
45547
|
+
addOverrideMicroVisualizationThreshold() {
|
|
45548
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45549
|
+
if (!visualization)
|
|
45550
|
+
return;
|
|
45551
|
+
const current = Array.isArray(visualization['thresholds']) ? [...visualization['thresholds']] : [];
|
|
45552
|
+
const lastMax = current.length ? current[current.length - 1]?.max : undefined;
|
|
45553
|
+
const nextMin = typeof lastMax === 'number' && Number.isFinite(lastMax) ? lastMax + 1 : 0;
|
|
45554
|
+
current.push({
|
|
45555
|
+
min: nextMin,
|
|
45556
|
+
max: nextMin + 30,
|
|
45557
|
+
tone: 'warning',
|
|
45558
|
+
});
|
|
45559
|
+
visualization['thresholds'] = current;
|
|
45560
|
+
if (visualization['tone'] === 'info') {
|
|
45561
|
+
delete visualization['tone'];
|
|
45562
|
+
}
|
|
45563
|
+
this.onColumnPropertyChange();
|
|
45564
|
+
this.validateRenderer();
|
|
45565
|
+
}
|
|
45566
|
+
applyDefaultOverrideMicroVisualizationThresholds() {
|
|
45567
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45568
|
+
if (!visualization)
|
|
45569
|
+
return;
|
|
45570
|
+
visualization['thresholds'] = [
|
|
45571
|
+
{ min: 0, max: 39, tone: 'danger' },
|
|
45572
|
+
{ min: 40, max: 69, tone: 'warning' },
|
|
45573
|
+
{ min: 70, max: 100, tone: 'success' },
|
|
45574
|
+
];
|
|
45575
|
+
delete visualization['tone'];
|
|
45576
|
+
this.onColumnPropertyChange();
|
|
45577
|
+
this.validateRenderer();
|
|
45578
|
+
}
|
|
45579
|
+
setOverrideMicroVisualizationThresholdNumber(index, bound, raw) {
|
|
45580
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45581
|
+
if (!visualization || !Array.isArray(visualization['thresholds']) || !visualization['thresholds'][index])
|
|
45582
|
+
return;
|
|
45583
|
+
const list = visualization['thresholds'].map((item) => ({ ...item }));
|
|
45584
|
+
const trimmed = String(raw ?? '').trim();
|
|
45585
|
+
if (!trimmed) {
|
|
45586
|
+
delete list[index][bound];
|
|
45587
|
+
}
|
|
45588
|
+
else {
|
|
45589
|
+
const parsed = Number(trimmed);
|
|
45590
|
+
if (Number.isFinite(parsed)) {
|
|
45591
|
+
list[index][bound] = parsed;
|
|
45592
|
+
}
|
|
45593
|
+
}
|
|
45594
|
+
visualization['thresholds'] = list;
|
|
45595
|
+
this.onColumnPropertyChange();
|
|
45596
|
+
this.validateRenderer();
|
|
45597
|
+
}
|
|
45598
|
+
setOverrideMicroVisualizationThresholdTone(index, tone) {
|
|
45599
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45600
|
+
if (!visualization || !Array.isArray(visualization['thresholds']) || !visualization['thresholds'][index])
|
|
45601
|
+
return;
|
|
45602
|
+
const list = visualization['thresholds'].map((item) => ({ ...item }));
|
|
45603
|
+
list[index].tone = tone;
|
|
45604
|
+
visualization['thresholds'] = list;
|
|
45605
|
+
this.onColumnPropertyChange();
|
|
45606
|
+
this.validateRenderer();
|
|
45607
|
+
}
|
|
45608
|
+
moveOverrideMicroVisualizationThreshold(index, delta) {
|
|
45609
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45610
|
+
if (!visualization || !Array.isArray(visualization['thresholds']))
|
|
45611
|
+
return;
|
|
45612
|
+
const target = index + delta;
|
|
45613
|
+
const list = [...visualization['thresholds']];
|
|
45614
|
+
if (index < 0 || index >= list.length || target < 0 || target >= list.length)
|
|
45615
|
+
return;
|
|
45616
|
+
const [moved] = list.splice(index, 1);
|
|
45617
|
+
list.splice(target, 0, moved);
|
|
45618
|
+
visualization['thresholds'] = list;
|
|
45619
|
+
this.onColumnPropertyChange();
|
|
45620
|
+
this.validateRenderer();
|
|
45621
|
+
}
|
|
45622
|
+
removeOverrideMicroVisualizationThreshold(index) {
|
|
45623
|
+
const visualization = this.ensureOverrideMicroVisualizationObject();
|
|
45624
|
+
if (!visualization || !Array.isArray(visualization['thresholds']))
|
|
45625
|
+
return;
|
|
45626
|
+
const list = [...visualization['thresholds']];
|
|
45627
|
+
if (index < 0 || index >= list.length)
|
|
45628
|
+
return;
|
|
45629
|
+
list.splice(index, 1);
|
|
45630
|
+
if (list.length > 0) {
|
|
45631
|
+
visualization['thresholds'] = list;
|
|
45632
|
+
}
|
|
45633
|
+
else {
|
|
45634
|
+
delete visualization['thresholds'];
|
|
45635
|
+
}
|
|
45636
|
+
this.onColumnPropertyChange();
|
|
45637
|
+
this.validateRenderer();
|
|
45638
|
+
}
|
|
45445
45639
|
getOverrideMicroVisualizationGuidanceText() {
|
|
45446
45640
|
const constraint = this.getOverrideMicroVisualizationConstraint();
|
|
45447
45641
|
if (this.getOverrideMicroVisualizationGuidance() === 'recommended') {
|
|
@@ -45489,11 +45683,15 @@ class ColumnsConfigEditorComponent {
|
|
|
45489
45683
|
}
|
|
45490
45684
|
// Renderer apply/preview state
|
|
45491
45685
|
rendererValidationErrors = [];
|
|
45686
|
+
get validationErrors() {
|
|
45687
|
+
return this.rendererValidationErrors;
|
|
45688
|
+
}
|
|
45492
45689
|
rendererImportWarnings = [];
|
|
45493
45690
|
rendererIsValid = true;
|
|
45494
45691
|
rendererPreviewEnabled = true;
|
|
45495
45692
|
rendererAppliedSnapshot = null;
|
|
45496
45693
|
previewRows = [];
|
|
45694
|
+
microVisualizationSampleValuesText = '15, 40, 69, 70, 98';
|
|
45497
45695
|
refreshRendererFieldOptions() {
|
|
45498
45696
|
const options = this.buildRendererFieldOptions();
|
|
45499
45697
|
const filtered = this.onlyVisibleRendererFields ? options.filter((o) => o.isVisible) : options;
|
|
@@ -46336,22 +46534,175 @@ class ColumnsConfigEditorComponent {
|
|
|
46336
46534
|
fallbackText: this.selectedColumn?.header || field,
|
|
46337
46535
|
};
|
|
46338
46536
|
}
|
|
46339
|
-
|
|
46537
|
+
ensureMicroVisualizationObject() {
|
|
46340
46538
|
if (!this.selectedColumn)
|
|
46341
|
-
return;
|
|
46539
|
+
return null;
|
|
46342
46540
|
const column = this.selectedColumn;
|
|
46343
46541
|
column.renderer = column.renderer || { type: 'microVisualization' };
|
|
46344
46542
|
column.renderer.type = 'microVisualization';
|
|
46345
46543
|
column.renderer.microVisualization = column.renderer.microVisualization || {};
|
|
46346
|
-
column.renderer.microVisualization.visualization
|
|
46347
|
-
|
|
46348
|
-
|
|
46349
|
-
|
|
46350
|
-
|
|
46351
|
-
column.renderer.microVisualization.visualization
|
|
46544
|
+
const existing = column.renderer.microVisualization.visualization;
|
|
46545
|
+
column.renderer.microVisualization.visualization =
|
|
46546
|
+
existing && typeof existing === 'object'
|
|
46547
|
+
? { ...existing, surface: 'table-cell' }
|
|
46548
|
+
: { ...this.createDefaultMicroVisualization(), surface: 'table-cell' };
|
|
46549
|
+
return column.renderer.microVisualization.visualization;
|
|
46550
|
+
}
|
|
46551
|
+
setMicroVisualizationProp(path, value) {
|
|
46552
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46553
|
+
if (!visualization)
|
|
46554
|
+
return;
|
|
46555
|
+
if (value === undefined || value === null || (path === 'tone' && value === '')) {
|
|
46556
|
+
delete visualization[path];
|
|
46557
|
+
}
|
|
46558
|
+
else {
|
|
46559
|
+
visualization[path] = value;
|
|
46560
|
+
}
|
|
46352
46561
|
this.onColumnPropertyChange();
|
|
46353
46562
|
this.validateRenderer();
|
|
46354
46563
|
}
|
|
46564
|
+
isMicroVisualizationThresholdsSupported() {
|
|
46565
|
+
return ['delta', 'bullet', 'radial', 'harveyBall', 'line', 'area', 'column', 'comparison'].includes(this.getMicroVisualizationKind());
|
|
46566
|
+
}
|
|
46567
|
+
getMicroVisualizationThresholds() {
|
|
46568
|
+
const thresholds = this.getRendererProp('microVisualization', 'visualization.thresholds');
|
|
46569
|
+
return Array.isArray(thresholds) ? thresholds : [];
|
|
46570
|
+
}
|
|
46571
|
+
addMicroVisualizationThreshold() {
|
|
46572
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46573
|
+
if (!visualization)
|
|
46574
|
+
return;
|
|
46575
|
+
const current = Array.isArray(visualization['thresholds']) ? [...visualization['thresholds']] : [];
|
|
46576
|
+
const lastMax = current.length ? current[current.length - 1]?.max : undefined;
|
|
46577
|
+
const nextMin = typeof lastMax === 'number' && Number.isFinite(lastMax) ? lastMax + 1 : 0;
|
|
46578
|
+
current.push({
|
|
46579
|
+
min: nextMin,
|
|
46580
|
+
max: nextMin + 30,
|
|
46581
|
+
tone: 'warning',
|
|
46582
|
+
});
|
|
46583
|
+
visualization['thresholds'] = current;
|
|
46584
|
+
if (visualization['tone'] === 'info') {
|
|
46585
|
+
delete visualization['tone'];
|
|
46586
|
+
}
|
|
46587
|
+
this.onColumnPropertyChange();
|
|
46588
|
+
this.validateRenderer();
|
|
46589
|
+
}
|
|
46590
|
+
applyDefaultMicroVisualizationThresholds() {
|
|
46591
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46592
|
+
if (!visualization)
|
|
46593
|
+
return;
|
|
46594
|
+
visualization['thresholds'] = [
|
|
46595
|
+
{ min: 0, max: 39, tone: 'danger' },
|
|
46596
|
+
{ min: 40, max: 69, tone: 'warning' },
|
|
46597
|
+
{ min: 70, max: 100, tone: 'success' },
|
|
46598
|
+
];
|
|
46599
|
+
delete visualization['tone'];
|
|
46600
|
+
this.onColumnPropertyChange();
|
|
46601
|
+
this.validateRenderer();
|
|
46602
|
+
}
|
|
46603
|
+
setMicroVisualizationThresholdNumber(index, bound, raw) {
|
|
46604
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46605
|
+
if (!visualization || !Array.isArray(visualization['thresholds']) || !visualization['thresholds'][index])
|
|
46606
|
+
return;
|
|
46607
|
+
const list = visualization['thresholds'].map((item) => ({ ...item }));
|
|
46608
|
+
const trimmed = String(raw ?? '').trim();
|
|
46609
|
+
if (!trimmed) {
|
|
46610
|
+
delete list[index][bound];
|
|
46611
|
+
}
|
|
46612
|
+
else {
|
|
46613
|
+
const parsed = Number(trimmed);
|
|
46614
|
+
if (Number.isFinite(parsed)) {
|
|
46615
|
+
list[index][bound] = parsed;
|
|
46616
|
+
}
|
|
46617
|
+
}
|
|
46618
|
+
visualization['thresholds'] = list;
|
|
46619
|
+
this.onColumnPropertyChange();
|
|
46620
|
+
this.validateRenderer();
|
|
46621
|
+
}
|
|
46622
|
+
setMicroVisualizationThresholdTone(index, tone) {
|
|
46623
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46624
|
+
if (!visualization || !Array.isArray(visualization['thresholds']) || !visualization['thresholds'][index])
|
|
46625
|
+
return;
|
|
46626
|
+
const list = visualization['thresholds'].map((item) => ({ ...item }));
|
|
46627
|
+
list[index].tone = tone;
|
|
46628
|
+
visualization['thresholds'] = list;
|
|
46629
|
+
this.onColumnPropertyChange();
|
|
46630
|
+
this.validateRenderer();
|
|
46631
|
+
}
|
|
46632
|
+
moveMicroVisualizationThreshold(index, delta) {
|
|
46633
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46634
|
+
if (!visualization || !Array.isArray(visualization['thresholds']))
|
|
46635
|
+
return;
|
|
46636
|
+
const target = index + delta;
|
|
46637
|
+
const list = [...visualization['thresholds']];
|
|
46638
|
+
if (index < 0 || index >= list.length || target < 0 || target >= list.length)
|
|
46639
|
+
return;
|
|
46640
|
+
const [moved] = list.splice(index, 1);
|
|
46641
|
+
list.splice(target, 0, moved);
|
|
46642
|
+
visualization['thresholds'] = list;
|
|
46643
|
+
this.onColumnPropertyChange();
|
|
46644
|
+
this.validateRenderer();
|
|
46645
|
+
}
|
|
46646
|
+
removeMicroVisualizationThreshold(index) {
|
|
46647
|
+
const visualization = this.ensureMicroVisualizationObject();
|
|
46648
|
+
if (!visualization || !Array.isArray(visualization['thresholds']))
|
|
46649
|
+
return;
|
|
46650
|
+
const list = [...visualization['thresholds']];
|
|
46651
|
+
if (index < 0 || index >= list.length)
|
|
46652
|
+
return;
|
|
46653
|
+
list.splice(index, 1);
|
|
46654
|
+
if (list.length > 0) {
|
|
46655
|
+
visualization['thresholds'] = list;
|
|
46656
|
+
}
|
|
46657
|
+
else {
|
|
46658
|
+
delete visualization['thresholds'];
|
|
46659
|
+
}
|
|
46660
|
+
this.onColumnPropertyChange();
|
|
46661
|
+
this.validateRenderer();
|
|
46662
|
+
}
|
|
46663
|
+
setMicroVisualizationSampleValuesText(raw) {
|
|
46664
|
+
this.microVisualizationSampleValuesText = raw;
|
|
46665
|
+
this.cdr.markForCheck();
|
|
46666
|
+
}
|
|
46667
|
+
getMicroVisualizationSampleValues() {
|
|
46668
|
+
const parsed = String(this.microVisualizationSampleValuesText || '')
|
|
46669
|
+
.split(',')
|
|
46670
|
+
.map((part) => Number(part.trim()))
|
|
46671
|
+
.filter((num) => Number.isFinite(num));
|
|
46672
|
+
return parsed.length > 0 ? parsed.slice(0, 8) : [15, 40, 69, 70, 98];
|
|
46673
|
+
}
|
|
46674
|
+
getPreviewMicroVisualizationHtmlForValue(sampleValue) {
|
|
46675
|
+
const field = this.selectedColumn?.field || 'value';
|
|
46676
|
+
const baseRow = this.previewRows?.[0] || {};
|
|
46677
|
+
const sampleRow = {
|
|
46678
|
+
...baseRow,
|
|
46679
|
+
[field]: sampleValue,
|
|
46680
|
+
value: sampleValue,
|
|
46681
|
+
total: typeof baseRow?.total === 'number' ? baseRow.total : 100,
|
|
46682
|
+
target: typeof baseRow?.target === 'number' ? baseRow.target : 80,
|
|
46683
|
+
baseline: typeof baseRow?.baseline === 'number' ? baseRow.baseline : 50,
|
|
46684
|
+
};
|
|
46685
|
+
const visualization = this.selectedColumn?.renderer?.microVisualization?.visualization;
|
|
46686
|
+
if (!visualization)
|
|
46687
|
+
return '';
|
|
46688
|
+
const resolved = { ...visualization };
|
|
46689
|
+
const expressions = [
|
|
46690
|
+
['value', 'valueExpr'], ['valueSuffix', 'valueSuffixExpr'], ['total', 'totalExpr'], ['target', 'targetExpr'], ['baseline', 'baselineExpr'],
|
|
46691
|
+
['points', 'pointsExpr'], ['segments', 'segmentsExpr'], ['thresholds', 'thresholdsExpr'], ['items', 'itemsExpr'],
|
|
46692
|
+
['tone', 'toneExpr'], ['ariaLabel', 'ariaLabelExpr'], ['fallbackText', 'fallbackTextExpr'],
|
|
46693
|
+
];
|
|
46694
|
+
for (const [property, expression] of expressions) {
|
|
46695
|
+
if (!resolved[expression])
|
|
46696
|
+
continue;
|
|
46697
|
+
const evaluated = this.evalMicroVisualizationExpression(resolved[expression], sampleRow);
|
|
46698
|
+
if (evaluated !== undefined)
|
|
46699
|
+
resolved[property] = evaluated;
|
|
46700
|
+
}
|
|
46701
|
+
if (typeof resolved['value'] !== 'number' || !Number.isFinite(resolved['value'])) {
|
|
46702
|
+
resolved['value'] = sampleValue;
|
|
46703
|
+
}
|
|
46704
|
+
return renderPraxisPresentationVisualizationHtml(resolved);
|
|
46705
|
+
}
|
|
46355
46706
|
// =============================
|
|
46356
46707
|
// Renderer: validation/apply/import/export/preview
|
|
46357
46708
|
// =============================
|
|
@@ -46952,6 +47303,18 @@ class ColumnsConfigEditorComponent {
|
|
|
46952
47303
|
if (evaluated !== undefined)
|
|
46953
47304
|
resolved[property] = evaluated;
|
|
46954
47305
|
}
|
|
47306
|
+
if (['delta', 'bullet', 'radial', 'harveyBall'].includes(resolved['kind']) &&
|
|
47307
|
+
(typeof resolved['value'] !== 'number' || !Number.isFinite(resolved['value']))) {
|
|
47308
|
+
const parsedValue = Number(resolved['value']);
|
|
47309
|
+
if (Number.isFinite(parsedValue) && String(resolved['value'] ?? '').trim() !== '') {
|
|
47310
|
+
resolved['value'] = parsedValue;
|
|
47311
|
+
}
|
|
47312
|
+
else {
|
|
47313
|
+
const sampleValues = this.getMicroVisualizationSampleValues();
|
|
47314
|
+
const rowIdx = Math.max(0, this.previewRows.indexOf(row));
|
|
47315
|
+
resolved['value'] = sampleValues[rowIdx % sampleValues.length] ?? 70;
|
|
47316
|
+
}
|
|
47317
|
+
}
|
|
46955
47318
|
return renderPraxisPresentationVisualizationHtml(resolved);
|
|
46956
47319
|
}
|
|
46957
47320
|
getMicroVisualizationGuidance() {
|
|
@@ -47098,14 +47461,37 @@ class ColumnsConfigEditorComponent {
|
|
|
47098
47461
|
getPreviewHtml(row) { const ht = this.selectedColumn?.renderer?.html; if (!ht?.template)
|
|
47099
47462
|
return String(ht?.emptyFallback || ''); return String(ht.template).replace(/\[\[([A-Za-z0-9_\.]+)\]\]/g, (_m, g1) => { const v = this.getNested(row, g1); return String(v ?? ''); }); }
|
|
47100
47463
|
trackByIdx = (_, item) => this.previewRows.indexOf(item);
|
|
47464
|
+
validateMicroVisualizationThresholds(thresholds, errs) {
|
|
47465
|
+
if (!Array.isArray(thresholds))
|
|
47466
|
+
return;
|
|
47467
|
+
thresholds.forEach((entry, idx) => {
|
|
47468
|
+
const hasMin = typeof entry?.min === 'number' && Number.isFinite(entry.min);
|
|
47469
|
+
const hasMax = typeof entry?.max === 'number' && Number.isFinite(entry.max);
|
|
47470
|
+
if (!hasMin && !hasMax) {
|
|
47471
|
+
errs.push(this.tx('columns.renderer.validation.microVisualization.thresholdEmptyBounds', 'Micro-visualization: band #{index} must define at least min or max.').replace('{index}', String(idx + 1)));
|
|
47472
|
+
}
|
|
47473
|
+
else if (hasMin && hasMax && entry.min > entry.max) {
|
|
47474
|
+
errs.push(this.tx('columns.renderer.validation.microVisualization.thresholdInvalidRange', 'Micro-visualization: band #{index} has min ({min}) greater than max ({max}).')
|
|
47475
|
+
.replace('{index}', String(idx + 1))
|
|
47476
|
+
.replace('{min}', String(entry.min))
|
|
47477
|
+
.replace('{max}', String(entry.max)));
|
|
47478
|
+
}
|
|
47479
|
+
});
|
|
47480
|
+
}
|
|
47101
47481
|
validateRenderer() {
|
|
47102
47482
|
const errs = [];
|
|
47103
47483
|
const col = this.selectedColumn;
|
|
47484
|
+
const overrides = Array.isArray(col?.conditionalRenderers) ? col.conditionalRenderers : [];
|
|
47485
|
+
for (const ov of overrides) {
|
|
47486
|
+
if (ov?.renderer?.type === 'microVisualization') {
|
|
47487
|
+
this.validateMicroVisualizationThresholds(ov.renderer.microVisualization?.visualization?.thresholds, errs);
|
|
47488
|
+
}
|
|
47489
|
+
}
|
|
47104
47490
|
const r = col?.renderer || null;
|
|
47105
47491
|
if (!r || !r.type) {
|
|
47106
|
-
// no renderer -> valid
|
|
47107
|
-
this.rendererValidationErrors =
|
|
47108
|
-
this.rendererIsValid =
|
|
47492
|
+
// no renderer -> valid unless conditional override has threshold errors
|
|
47493
|
+
this.rendererValidationErrors = errs;
|
|
47494
|
+
this.rendererIsValid = errs.length === 0;
|
|
47109
47495
|
this.cdr.markForCheck();
|
|
47110
47496
|
return;
|
|
47111
47497
|
}
|
|
@@ -47211,6 +47597,7 @@ class ColumnsConfigEditorComponent {
|
|
|
47211
47597
|
if (visualization.kind === 'processFlow' && !hasItems) {
|
|
47212
47598
|
errs.push('Microvisualização: process flow exige items ou itemsExpr.');
|
|
47213
47599
|
}
|
|
47600
|
+
this.validateMicroVisualizationThresholds(visualization.thresholds, errs);
|
|
47214
47601
|
}
|
|
47215
47602
|
}
|
|
47216
47603
|
if (r.type === 'avatar') {
|
|
@@ -49089,18 +49476,162 @@ class ColumnsConfigEditorComponent {
|
|
|
49089
49476
|
}
|
|
49090
49477
|
<mat-form-field appearance="outline">
|
|
49091
49478
|
<mat-label>{{ tx('columns.renderer.microVisualization.tone', 'Tone') }}</mat-label>
|
|
49092
|
-
<mat-select [ngModel]="getRendererProp('microVisualization','visualization.tone')
|
|
49479
|
+
<mat-select [ngModel]="getRendererProp('microVisualization','visualization.tone') ?? ''" [ngModelOptions]="{standalone: true}" (ngModelChange)="setMicroVisualizationProp('tone', $event)">
|
|
49480
|
+
<mat-option [value]="''">{{ tx('columns.renderer.microVisualization.tone.auto', 'Automatic (by thresholds / semantic)') }}</mat-option>
|
|
49093
49481
|
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
49094
49482
|
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
49095
49483
|
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
49096
49484
|
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
49097
49485
|
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
49486
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
49098
49487
|
</mat-select>
|
|
49099
49488
|
</mat-form-field>
|
|
49100
49489
|
<mat-form-field appearance="outline">
|
|
49101
49490
|
<mat-label>{{ tx('columns.renderer.microVisualization.fallbackText', 'Accessible fallback text') }}</mat-label>
|
|
49102
49491
|
<input matInput [value]="getRendererProp('microVisualization','visualization.fallbackText') || ''" (input)="setMicroVisualizationProp('fallbackText', $any($event.target).value)" />
|
|
49103
49492
|
</mat-form-field>
|
|
49493
|
+
<div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
|
|
49494
|
+
{{ tx('columns.renderer.microVisualization.tone.precedenceHint', 'In Automatic mode, color is resolved from threshold bands or value sign. A fixed tone overrides conditional bands.') }}
|
|
49495
|
+
</div>
|
|
49496
|
+
@if (isMicroVisualizationThresholdsSupported()) {
|
|
49497
|
+
<div
|
|
49498
|
+
data-testid="micro-viz-thresholds-section"
|
|
49499
|
+
style="grid-column: 1/-1; display: grid; gap: 10px; padding: 12px; border: 1px solid var(--md-sys-color-outline-variant); border-radius: 8px;"
|
|
49500
|
+
>
|
|
49501
|
+
<div style="display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap;">
|
|
49502
|
+
<div>
|
|
49503
|
+
<div style="font-weight: 600;">
|
|
49504
|
+
{{ tx('columns.renderer.microVisualization.thresholds.title', 'Color bands (thresholds)') }}
|
|
49505
|
+
</div>
|
|
49506
|
+
<div class="renderer-hint" style="opacity: .78;">
|
|
49507
|
+
{{ tx('columns.renderer.microVisualization.thresholds.description', 'Evaluates top-to-bottom (first matching band wins). Both min and max bounds are inclusive (min <= value <= max).') }}
|
|
49508
|
+
</div>
|
|
49509
|
+
</div>
|
|
49510
|
+
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
|
49511
|
+
<button
|
|
49512
|
+
mat-stroked-button
|
|
49513
|
+
type="button"
|
|
49514
|
+
data-testid="micro-viz-add-threshold"
|
|
49515
|
+
(click)="addMicroVisualizationThreshold()"
|
|
49516
|
+
>
|
|
49517
|
+
<mat-icon>add</mat-icon>
|
|
49518
|
+
{{ tx('columns.renderer.microVisualization.thresholds.add', 'Add threshold') }}
|
|
49519
|
+
</button>
|
|
49520
|
+
<button
|
|
49521
|
+
mat-stroked-button
|
|
49522
|
+
type="button"
|
|
49523
|
+
data-testid="micro-viz-preset-thresholds"
|
|
49524
|
+
(click)="applyDefaultMicroVisualizationThresholds()"
|
|
49525
|
+
>
|
|
49526
|
+
<mat-icon>traffic</mat-icon>
|
|
49527
|
+
{{ tx('columns.renderer.microVisualization.thresholds.preset', 'Traffic-light preset (70+ / 40–69 / ≤39)') }}
|
|
49528
|
+
</button>
|
|
49529
|
+
</div>
|
|
49530
|
+
</div>
|
|
49531
|
+
@if (!getMicroVisualizationThresholds().length) {
|
|
49532
|
+
<div class="renderer-hint" style="opacity: .75;">
|
|
49533
|
+
{{ tx('columns.renderer.microVisualization.thresholds.empty', 'No threshold bands configured. Add bands or apply the traffic-light preset to color values automatically.') }}
|
|
49534
|
+
</div>
|
|
49535
|
+
}
|
|
49536
|
+
@for (threshold of getMicroVisualizationThresholds(); track $index) {
|
|
49537
|
+
<div
|
|
49538
|
+
data-testid="micro-viz-threshold-row"
|
|
49539
|
+
style="display: grid; grid-template-columns: minmax(110px, 1fr) minmax(110px, 1fr) minmax(140px, 1fr) auto; gap: 8px; align-items: center;"
|
|
49540
|
+
>
|
|
49541
|
+
<mat-form-field appearance="outline">
|
|
49542
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.min', 'Min (inclusive)') }}</mat-label>
|
|
49543
|
+
<input
|
|
49544
|
+
matInput
|
|
49545
|
+
type="number"
|
|
49546
|
+
data-testid="micro-viz-threshold-min"
|
|
49547
|
+
[value]="threshold.min ?? ''"
|
|
49548
|
+
(input)="setMicroVisualizationThresholdNumber($index, 'min', $any($event.target).value)"
|
|
49549
|
+
/>
|
|
49550
|
+
</mat-form-field>
|
|
49551
|
+
<mat-form-field appearance="outline">
|
|
49552
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.max', 'Max (inclusive)') }}</mat-label>
|
|
49553
|
+
<input
|
|
49554
|
+
matInput
|
|
49555
|
+
type="number"
|
|
49556
|
+
data-testid="micro-viz-threshold-max"
|
|
49557
|
+
[value]="threshold.max ?? ''"
|
|
49558
|
+
(input)="setMicroVisualizationThresholdNumber($index, 'max', $any($event.target).value)"
|
|
49559
|
+
/>
|
|
49560
|
+
</mat-form-field>
|
|
49561
|
+
<mat-form-field appearance="outline">
|
|
49562
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.tone', 'Band tone') }}</mat-label>
|
|
49563
|
+
<mat-select
|
|
49564
|
+
data-testid="micro-viz-threshold-tone"
|
|
49565
|
+
[ngModel]="threshold.tone || 'info'"
|
|
49566
|
+
[ngModelOptions]="{standalone: true}"
|
|
49567
|
+
(ngModelChange)="setMicroVisualizationThresholdTone($index, $event)"
|
|
49568
|
+
>
|
|
49569
|
+
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
49570
|
+
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
49571
|
+
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
49572
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
49573
|
+
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
49574
|
+
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
49575
|
+
</mat-select>
|
|
49576
|
+
</mat-form-field>
|
|
49577
|
+
<div style="display: flex; gap: 4px; align-items: center;">
|
|
49578
|
+
<button
|
|
49579
|
+
praxisIconButton="arrow_upward"
|
|
49580
|
+
size="dense"
|
|
49581
|
+
type="button"
|
|
49582
|
+
data-testid="micro-viz-threshold-up"
|
|
49583
|
+
[disabled]="$index === 0"
|
|
49584
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move threshold up')"
|
|
49585
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move threshold up')"
|
|
49586
|
+
(click)="moveMicroVisualizationThreshold($index, -1)"
|
|
49587
|
+
></button>
|
|
49588
|
+
<button
|
|
49589
|
+
praxisIconButton="arrow_downward"
|
|
49590
|
+
size="dense"
|
|
49591
|
+
type="button"
|
|
49592
|
+
data-testid="micro-viz-threshold-down"
|
|
49593
|
+
[disabled]="$index === getMicroVisualizationThresholds().length - 1"
|
|
49594
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move threshold down')"
|
|
49595
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move threshold down')"
|
|
49596
|
+
(click)="moveMicroVisualizationThreshold($index, 1)"
|
|
49597
|
+
></button>
|
|
49598
|
+
<button
|
|
49599
|
+
praxisIconButton="delete_outline"
|
|
49600
|
+
size="dense"
|
|
49601
|
+
type="button"
|
|
49602
|
+
data-testid="micro-viz-threshold-remove"
|
|
49603
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove threshold')"
|
|
49604
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove threshold')"
|
|
49605
|
+
(click)="removeMicroVisualizationThreshold($index)"
|
|
49606
|
+
></button>
|
|
49607
|
+
</div>
|
|
49608
|
+
</div>
|
|
49609
|
+
}
|
|
49610
|
+
@if (isMicroVisualizationValueKind()) {
|
|
49611
|
+
<mat-form-field appearance="outline">
|
|
49612
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.sampleValues', 'Preview sample values (comma-separated)') }}</mat-label>
|
|
49613
|
+
<input
|
|
49614
|
+
matInput
|
|
49615
|
+
data-testid="micro-viz-sample-values-input"
|
|
49616
|
+
[value]="microVisualizationSampleValuesText"
|
|
49617
|
+
(input)="setMicroVisualizationSampleValuesText($any($event.target).value)"
|
|
49618
|
+
/>
|
|
49619
|
+
</mat-form-field>
|
|
49620
|
+
<div
|
|
49621
|
+
data-testid="micro-viz-sample-preview"
|
|
49622
|
+
style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center;"
|
|
49623
|
+
>
|
|
49624
|
+
@for (sampleVal of getMicroVisualizationSampleValues(); track $index) {
|
|
49625
|
+
<span
|
|
49626
|
+
class="pfx-micro-viz-cell"
|
|
49627
|
+
[attr.data-sample-value]="sampleVal"
|
|
49628
|
+
[innerHTML]="getPreviewMicroVisualizationHtmlForValue(sampleVal)"
|
|
49629
|
+
></span>
|
|
49630
|
+
}
|
|
49631
|
+
</div>
|
|
49632
|
+
}
|
|
49633
|
+
</div>
|
|
49634
|
+
}
|
|
49104
49635
|
<div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
|
|
49105
49636
|
{{ tx('columns.renderer.microVisualization.hint', 'Use a value for indicators, points for trends, segments for stacked bars, and items for process flows. The table keeps the visual compact and exposes fallback text to assistive technology.') }}
|
|
49106
49637
|
</div>
|
|
@@ -50001,14 +50532,79 @@ class ColumnsConfigEditorComponent {
|
|
|
50001
50532
|
}
|
|
50002
50533
|
<mat-form-field appearance="outline">
|
|
50003
50534
|
<mat-label>{{ tx('columns.renderer.microVisualization.tone', 'Tone') }}</mat-label>
|
|
50004
|
-
<mat-select [ngModel]="getOverrideMicroVisualizationProp('tone') || '
|
|
50535
|
+
<mat-select [ngModel]="getOverrideMicroVisualizationProp('tone') || ''" [ngModelOptions]="{standalone:true}" (ngModelChange)="setOverrideMicroVisualizationProp('tone', $event || undefined)">
|
|
50536
|
+
<mat-option value="">{{ tx('columns.renderer.microVisualization.tone.auto', 'Automatic (thresholds / default)') }}</mat-option>
|
|
50005
50537
|
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
50006
50538
|
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
50007
50539
|
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
50008
50540
|
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
50009
50541
|
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
50542
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
50010
50543
|
</mat-select>
|
|
50544
|
+
<mat-hint>{{ tx('columns.renderer.microVisualization.tone.precedenceHint', 'Fixed tone overrides thresholds. Choose Automatic to let color bands control the tone.') }}</mat-hint>
|
|
50011
50545
|
</mat-form-field>
|
|
50546
|
+
@if (isOverrideMicroVisualizationThresholdsSupported()) {
|
|
50547
|
+
<div class="micro-viz-thresholds-section" data-testid="override-micro-viz-thresholds-section">
|
|
50548
|
+
<div class="compose-header">
|
|
50549
|
+
<div>
|
|
50550
|
+
<div class="section-subtitle">{{ tx('columns.renderer.microVisualization.thresholds.title', 'Color bands (thresholds)') }}</div>
|
|
50551
|
+
<div class="field-hint">{{ tx('columns.renderer.microVisualization.thresholds.hint', 'First matching band wins (min <= value <= max). Leave min or max empty for open-ended ranges.') }}</div>
|
|
50552
|
+
</div>
|
|
50553
|
+
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
50554
|
+
<button mat-stroked-button type="button" data-testid="override-micro-viz-preset-thresholds" (click)="applyDefaultOverrideMicroVisualizationThresholds()">
|
|
50555
|
+
<mat-icon>palette</mat-icon>
|
|
50556
|
+
{{ tx('columns.renderer.microVisualization.thresholds.applyPreset', 'Traffic-light preset') }}
|
|
50557
|
+
</button>
|
|
50558
|
+
<button mat-stroked-button type="button" data-testid="override-micro-viz-add-threshold" (click)="addOverrideMicroVisualizationThreshold()">
|
|
50559
|
+
<mat-icon>add</mat-icon>
|
|
50560
|
+
{{ tx('columns.renderer.microVisualization.thresholds.add', 'Add band') }}
|
|
50561
|
+
</button>
|
|
50562
|
+
</div>
|
|
50563
|
+
</div>
|
|
50564
|
+
@if (getOverrideMicroVisualizationProp('tone') && getOverrideMicroVisualizationThresholds().length > 0) {
|
|
50565
|
+
<div class="field-hint micro-viz-guidance is-conditional">
|
|
50566
|
+
{{ tx('columns.renderer.microVisualization.thresholds.overriddenByToneWarning', 'A fixed tone is selected above and will override these color bands. Switch Tone to Automatic so thresholds take effect.') }}
|
|
50567
|
+
</div>
|
|
50568
|
+
}
|
|
50569
|
+
@if (getOverrideMicroVisualizationThresholds().length === 0) {
|
|
50570
|
+
<div class="field-hint">{{ tx('columns.renderer.microVisualization.thresholds.empty', 'No color bands configured.') }}</div>
|
|
50571
|
+
}
|
|
50572
|
+
@for (threshold of getOverrideMicroVisualizationThresholds(); track $index; let idx = $index) {
|
|
50573
|
+
<div class="form-row three-columns micro-viz-threshold-row" [attr.data-testid]="'override-micro-viz-threshold-row-' + idx">
|
|
50574
|
+
<mat-form-field appearance="outline">
|
|
50575
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.min', 'Min') }}</mat-label>
|
|
50576
|
+
<input matInput type="number" [value]="threshold.min ?? ''" (input)="setOverrideMicroVisualizationThresholdNumber(idx, 'min', $any($event.target).value)" />
|
|
50577
|
+
</mat-form-field>
|
|
50578
|
+
<mat-form-field appearance="outline">
|
|
50579
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.max', 'Max') }}</mat-label>
|
|
50580
|
+
<input matInput type="number" [value]="threshold.max ?? ''" (input)="setOverrideMicroVisualizationThresholdNumber(idx, 'max', $any($event.target).value)" />
|
|
50581
|
+
</mat-form-field>
|
|
50582
|
+
<div style="display:flex; gap:6px; align-items:flex-start;">
|
|
50583
|
+
<mat-form-field appearance="outline" style="flex:1;">
|
|
50584
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.tone', 'Band tone') }}</mat-label>
|
|
50585
|
+
<mat-select [ngModel]="threshold.tone || 'neutral'" [ngModelOptions]="{standalone:true}" (ngModelChange)="setOverrideMicroVisualizationThresholdTone(idx, $event)">
|
|
50586
|
+
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
50587
|
+
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
50588
|
+
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
50589
|
+
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
50590
|
+
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
50591
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
50592
|
+
</mat-select>
|
|
50593
|
+
</mat-form-field>
|
|
50594
|
+
<button mat-icon-button type="button" (click)="moveOverrideMicroVisualizationThreshold(idx, -1)" [disabled]="idx === 0" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move band up')">
|
|
50595
|
+
<mat-icon>arrow_upward</mat-icon>
|
|
50596
|
+
</button>
|
|
50597
|
+
<button mat-icon-button type="button" (click)="moveOverrideMicroVisualizationThreshold(idx, 1)" [disabled]="idx === getOverrideMicroVisualizationThresholds().length - 1" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move band down')">
|
|
50598
|
+
<mat-icon>arrow_downward</mat-icon>
|
|
50599
|
+
</button>
|
|
50600
|
+
<button mat-icon-button type="button" color="warn" (click)="removeOverrideMicroVisualizationThreshold(idx)" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove band')">
|
|
50601
|
+
<mat-icon>delete</mat-icon>
|
|
50602
|
+
</button>
|
|
50603
|
+
</div>
|
|
50604
|
+
</div>
|
|
50605
|
+
}
|
|
50606
|
+
</div>
|
|
50607
|
+
}
|
|
50012
50608
|
<mat-form-field appearance="outline">
|
|
50013
50609
|
<mat-label>{{ tx('columns.renderer.microVisualization.fallbackText', 'Accessible fallback text') }}</mat-label>
|
|
50014
50610
|
<input matInput [value]="getOverrideMicroVisualizationProp('fallbackText') || ''" (input)="setOverrideMicroVisualizationProp('fallbackText', $any($event.target).value)" />
|
|
@@ -50024,7 +50620,7 @@ class ColumnsConfigEditorComponent {
|
|
|
50024
50620
|
</div>
|
|
50025
50621
|
</div>
|
|
50026
50622
|
</div>
|
|
50027
|
-
`, isInline: true, styles: [":host{display:block;min-width:0;container-type:inline-size;container-name:table-columns-editor}.columns-config-editor{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;gap:16px}.educational-card{background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);margin-bottom:12px}.inline-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-primary)}.help-icon-button{vertical-align:middle}.global-config-accordion{margin-bottom:16px}.global-config-panel{background:var(--md-sys-color-surface-container);border-left:4px solid var(--md-sys-color-secondary)}.config-panel-content{padding:16px 20px 20px}.config-layout{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start}.config-group{display:flex;flex-direction:column;min-width:0}.config-group:not(.features-group){flex:0 0 auto}.features-group{flex:1 1 300px;min-width:300px}.control-section{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface);margin:0}.control-status{font-weight:400;color:var(--md-sys-color-on-surface-variant);font-size:.75rem;margin-left:4px}.visibility-toggle-group,.alignment-toggle-group{display:flex}.visibility-toggle-group .mat-button-toggle{min-width:90px;height:40px}.alignment-toggle-group .mat-button-toggle{min-width:56px;width:auto;height:40px;padding:0 8px}.features-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-top:4px}.feature-checkbox{justify-self:start}.master-detail-layout{min-width:0;display:flex;flex:1;gap:16px;min-height:0}.master-panel{flex:0 0 350px;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.list-header{display:flex;justify-content:space-between;align-items:center;padding:16px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.list-header h3{margin:0;font-size:1.1rem;font-weight:500}.add-column-fab{transform:scale(.7)}.columns-list-container{flex:1;overflow-y:auto}.columns-list{padding:0}.column-item{border-bottom:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:background-color .2s}.column-item:hover{background:var(--md-sys-color-surface-container)}.column-item.selected{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.column-item-content{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px}.column-main-info{flex:1;display:flex;flex-direction:column;gap:4px}.column-header{display:flex;align-items:center;gap:8px;width:100%}.drag-handle{cursor:grab;color:var(--md-sys-color-on-surface-variant);font-size:18px;flex-shrink:0}.column-text-info{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.column-title{font-weight:600;font-size:.9rem;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-field{font-size:.75rem;color:var(--md-sys-color-on-surface-variant);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-indicators{display:flex;align-items:center;gap:6px;flex-shrink:0}.column-type-icon,.mapping-indicator-icon,.renderer-indicator-icon{font-size:16px;color:var(--md-sys-color-on-surface-variant)}.visibility-checkbox{transform:scale(.9)}.remove-button{color:var(--md-sys-color-error);opacity:.7;transition:opacity .2s}.remove-button:hover{opacity:1}.detail-panel{min-width:0;flex:1;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.no-selection-message{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;text-align:center;padding:48px;color:var(--md-sys-color-on-surface-variant)}.no-selection-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px}.editor-header{padding:16px 24px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.editor-title{margin:0;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.column-form{flex:1;padding:24px;overflow:visible}.form-row{display:flex;gap:16px;margin-bottom:24px;align-items:flex-start}.field-input,.header-input,.width-input,.data-type-input{flex:1}.header-input{flex:2}.alignment-group,.sticky-group{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface)}.renderer-grid,.renderer-config{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px}.compose-preset-panel{grid-column:1/-1;display:grid;gap:12px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.compose-preset-copy,.compose-editor-heading{display:grid;gap:4px}.compose-preset-copy strong,.compose-editor-heading strong{color:var(--md-sys-color-on-surface);font-weight:600}.compose-preset-actions,.compose-item-actions{display:flex;flex-wrap:wrap;gap:8px}.compose-preset-actions button,.compose-item-actions button{min-height:36px;white-space:normal;text-align:left;line-height:1.2}.compose-preset-actions--inline{margin:0 0 12px}.compose-editor-heading{margin-bottom:12px}.renderer-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}.cond-ov-item{min-width:0;flex-wrap:wrap}.cond-ov-item>span{min-width:0;overflow-wrap:anywhere}.cond-ov-item>.spacer{margin-left:auto}.renderer-errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);padding:8px 12px;border-radius:6px;font-size:.85rem}.renderer-preview{margin-top:8px;padding:8px 12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.renderer-preview-list{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.renderer-preview-list .pfx-compose{display:inline-flex;gap:6px;align-items:center}.pfx-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:10px;font-size:12px;line-height:1}.pfx-badge-icon{font-size:14px;width:14px;height:14px}.pfx-badge--plain{border:1px solid transparent;color:inherit;background:transparent}.pfx-badge--outlined{border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);background:transparent}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn,.pfx-badge--filled-danger{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--filled-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-badge--filled-info{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}.pfx-badge--filled-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border:1px solid var(--md-sys-color-outline-variant)}.pfx-badge--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge--soft-warn,.pfx-badge--soft-danger{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-badge--soft-success,.pfx-badge--soft-info{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-badge--soft-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image{display:inline-block;border-radius:4px;object-fit:cover}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;border:1px solid transparent}.pfx-chip--plain{background:transparent;border-color:transparent;color:var(--md-sys-color-on-surface)}.pfx-chip--outlined{border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn,.pfx-chip--filled-danger{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--filled-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-chip--filled-info{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}.pfx-chip--filled-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.pfx-chip--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-chip--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-chip--soft-warn,.pfx-chip--soft-danger{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-chip--soft-success,.pfx-chip--soft-info{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-chip--soft-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.pfx-progress{position:relative;width:120px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary)}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600;width:32px;height:32px}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}@container table-columns-editor (max-width: 800px){.column-form{padding:12px}.cond-ov-item{align-items:flex-start}.cond-ov-item>.spacer{display:none}.master-panel{flex:0 0 220px;min-width:0}.column-item{height:auto;min-height:96px}.column-item-content{display:grid;grid-template-columns:18px minmax(0,1fr) auto;padding:10px 0;gap:4px}.column-main-info,.column-header{display:contents}.drag-handle{grid-row:1;grid-column:1}.column-text-info{grid-row:1;grid-column:2/4}.column-title{white-space:normal;overflow-wrap:anywhere}.column-indicators{grid-row:2;grid-column:2;gap:2px}.remove-button{grid-row:2;grid-column:3}.detail-panel{min-width:0}.form-row{flex-direction:column;gap:12px}.config-layout{flex-direction:column;gap:20px}.features-group{min-width:auto}.features-grid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px}.visibility-toggle-group .mat-button-toggle{min-width:80px;font-size:.875rem}}@container table-columns-editor (max-width: 600px){.master-detail-layout{flex-direction:column}.master-panel{flex:0 0 auto;width:100%;max-height:240px}}@container table-columns-editor (max-width: 480px){.visibility-toggle-group .mat-button-toggle{min-width:70px;font-size:.8rem}.alignment-toggle-group .mat-button-toggle{min-width:48px;padding:0 6px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i10$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i10$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i9.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i9.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i7$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i10$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i11$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i8.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i6.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i6.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i6.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i6.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i6.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i14.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: VisualFormulaBuilderComponent, selector: "visual-formula-builder", inputs: ["availableDataSchema", "currentFormula"], outputs: ["formulaChange", "generatedExpressionChange"] }, { kind: "component", type: ValueMappingEditorComponent, selector: "value-mapping-editor", inputs: ["currentMapping", "keyInputType", "labelKey", "labelValue"], outputs: ["mappingChange"] }, { kind: "component", type: DataFormatterComponent, selector: "data-formatter", inputs: ["columnType", "currentFormat"], outputs: ["formatChange"] }, { kind: "component", type: TableRatingCellComponent, selector: "praxis-table-rating", inputs: ["itemsCount", "value", "size", "ratingColor", "outlineColor", "ariaLabel"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
50623
|
+
`, isInline: true, styles: [":host{display:block;min-width:0;container-type:inline-size;container-name:table-columns-editor}.columns-config-editor{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;gap:16px}.educational-card{background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);margin-bottom:12px}.inline-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-primary)}.help-icon-button{vertical-align:middle}.global-config-accordion{margin-bottom:16px}.global-config-panel{background:var(--md-sys-color-surface-container);border-left:4px solid var(--md-sys-color-secondary)}.config-panel-content{padding:16px 20px 20px}.config-layout{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start}.config-group{display:flex;flex-direction:column;min-width:0}.config-group:not(.features-group){flex:0 0 auto}.features-group{flex:1 1 300px;min-width:300px}.control-section{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface);margin:0}.control-status{font-weight:400;color:var(--md-sys-color-on-surface-variant);font-size:.75rem;margin-left:4px}.visibility-toggle-group,.alignment-toggle-group{display:flex}.visibility-toggle-group .mat-button-toggle{min-width:90px;height:40px}.alignment-toggle-group .mat-button-toggle{min-width:56px;width:auto;height:40px;padding:0 8px}.features-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-top:4px}.feature-checkbox{justify-self:start}.master-detail-layout{min-width:0;display:flex;flex:1;gap:16px;min-height:0}.master-panel{flex:0 0 350px;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.list-header{display:flex;justify-content:space-between;align-items:center;padding:16px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.list-header h3{margin:0;font-size:1.1rem;font-weight:500}.add-column-fab{transform:scale(.7)}.columns-list-container{flex:1;overflow-y:auto}.columns-list{padding:0}.column-item{border-bottom:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:background-color .2s}.column-item:hover{background:var(--md-sys-color-surface-container)}.column-item.selected{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.column-item-content{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px}.column-main-info{flex:1;display:flex;flex-direction:column;gap:4px}.column-header{display:flex;align-items:center;gap:8px;width:100%}.drag-handle{cursor:grab;color:var(--md-sys-color-on-surface-variant);font-size:18px;flex-shrink:0}.column-text-info{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.column-title{font-weight:600;font-size:.9rem;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-field{font-size:.75rem;color:var(--md-sys-color-on-surface-variant);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-indicators{display:flex;align-items:center;gap:6px;flex-shrink:0}.column-type-icon,.mapping-indicator-icon,.renderer-indicator-icon{font-size:16px;color:var(--md-sys-color-on-surface-variant)}.visibility-checkbox{transform:scale(.9)}.remove-button{color:var(--md-sys-color-error);opacity:.7;transition:opacity .2s}.remove-button:hover{opacity:1}.detail-panel{min-width:0;flex:1;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.no-selection-message{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;text-align:center;padding:48px;color:var(--md-sys-color-on-surface-variant)}.no-selection-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px}.editor-header{padding:16px 24px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.editor-title{margin:0;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.column-form{flex:1;padding:24px;overflow:visible}.form-row{display:flex;gap:16px;margin-bottom:24px;align-items:flex-start}.field-input,.header-input,.width-input,.data-type-input{flex:1}.header-input{flex:2}.alignment-group,.sticky-group{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface)}.renderer-grid,.renderer-config{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px}.compose-preset-panel{grid-column:1/-1;display:grid;gap:12px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.compose-preset-copy,.compose-editor-heading{display:grid;gap:4px}.compose-preset-copy strong,.compose-editor-heading strong{color:var(--md-sys-color-on-surface);font-weight:600}.compose-preset-actions,.compose-item-actions{display:flex;flex-wrap:wrap;gap:8px}.compose-preset-actions button,.compose-item-actions button{min-height:36px;white-space:normal;text-align:left;line-height:1.2}.compose-preset-actions--inline{margin:0 0 12px}.compose-editor-heading{margin-bottom:12px}.renderer-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}.cond-ov-item{min-width:0;flex-wrap:wrap}.cond-ov-item>span{min-width:0;overflow-wrap:anywhere}.cond-ov-item>.spacer{margin-left:auto}.renderer-errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);padding:8px 12px;border-radius:6px;font-size:.85rem}.renderer-preview{margin-top:8px;padding:8px 12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.renderer-preview-list{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.renderer-preview-list .pfx-compose{display:inline-flex;gap:6px;align-items:center}.pfx-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:10px;font-size:12px;line-height:1}.pfx-badge-icon{font-size:14px;width:14px;height:14px}.pfx-badge--plain{border:1px solid transparent;color:inherit;background:transparent}.pfx-badge--outlined{border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);background:transparent}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn,.pfx-badge--filled-danger{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--filled-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-badge--filled-info{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}.pfx-badge--filled-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border:1px solid var(--md-sys-color-outline-variant)}.pfx-badge--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge--soft-warn,.pfx-badge--soft-danger{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-badge--soft-success,.pfx-badge--soft-info{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-badge--soft-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image{display:inline-block;border-radius:4px;object-fit:cover}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;border:1px solid transparent}.pfx-chip--plain{background:transparent;border-color:transparent;color:var(--md-sys-color-on-surface)}.pfx-chip--outlined{border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn,.pfx-chip--filled-danger{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--filled-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-chip--filled-info{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}.pfx-chip--filled-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.pfx-chip--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-chip--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-chip--soft-warn,.pfx-chip--soft-danger{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-chip--soft-success,.pfx-chip--soft-info{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.pfx-chip--soft-basic{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.pfx-progress{position:relative;width:120px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary)}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600;width:32px;height:32px}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}@container table-columns-editor (max-width: 800px){.column-form{padding:12px}.cond-ov-item{align-items:flex-start}.cond-ov-item>.spacer{display:none}.master-panel{flex:0 0 220px;min-width:0}.column-item{height:auto;min-height:96px}.column-item-content{display:grid;grid-template-columns:18px minmax(0,1fr) auto;padding:10px 0;gap:4px}.column-main-info,.column-header{display:contents}.drag-handle{grid-row:1;grid-column:1}.column-text-info{grid-row:1;grid-column:2/4}.column-title{white-space:normal;overflow-wrap:anywhere}.column-indicators{grid-row:2;grid-column:2;gap:2px}.remove-button{grid-row:2;grid-column:3}.detail-panel{min-width:0}.form-row{flex-direction:column;gap:12px}.config-layout{flex-direction:column;gap:20px}.features-group{min-width:auto}.features-grid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px}.visibility-toggle-group .mat-button-toggle{min-width:80px;font-size:.875rem}}@container table-columns-editor (max-width: 600px){.master-detail-layout{flex-direction:column}.master-panel{flex:0 0 auto;width:100%;max-height:240px}}@container table-columns-editor (max-width: 480px){.visibility-toggle-group .mat-button-toggle{min-width:70px;font-size:.8rem}.alignment-toggle-group .mat-button-toggle{min-width:48px;padding:0 6px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i10$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i10$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i9.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i9.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i7$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i10$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i11$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i8.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i6.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i6.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i6.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i6.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i6.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i14.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: VisualFormulaBuilderComponent, selector: "visual-formula-builder", inputs: ["availableDataSchema", "currentFormula"], outputs: ["formulaChange", "generatedExpressionChange"] }, { kind: "component", type: ValueMappingEditorComponent, selector: "value-mapping-editor", inputs: ["currentMapping", "keyInputType", "labelKey", "labelValue"], outputs: ["mappingChange"] }, { kind: "component", type: DataFormatterComponent, selector: "data-formatter", inputs: ["columnType", "currentFormat"], outputs: ["formatChange"] }, { kind: "component", type: TableRatingCellComponent, selector: "praxis-table-rating", inputs: ["itemsCount", "value", "size", "ratingColor", "outlineColor", "ariaLabel"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
50028
50624
|
}
|
|
50029
50625
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ColumnsConfigEditorComponent, decorators: [{
|
|
50030
50626
|
type: Component,
|
|
@@ -51115,18 +51711,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
51115
51711
|
}
|
|
51116
51712
|
<mat-form-field appearance="outline">
|
|
51117
51713
|
<mat-label>{{ tx('columns.renderer.microVisualization.tone', 'Tone') }}</mat-label>
|
|
51118
|
-
<mat-select [ngModel]="getRendererProp('microVisualization','visualization.tone')
|
|
51714
|
+
<mat-select [ngModel]="getRendererProp('microVisualization','visualization.tone') ?? ''" [ngModelOptions]="{standalone: true}" (ngModelChange)="setMicroVisualizationProp('tone', $event)">
|
|
51715
|
+
<mat-option [value]="''">{{ tx('columns.renderer.microVisualization.tone.auto', 'Automatic (by thresholds / semantic)') }}</mat-option>
|
|
51119
51716
|
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
51120
51717
|
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
51121
51718
|
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
51122
51719
|
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
51123
51720
|
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
51721
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
51124
51722
|
</mat-select>
|
|
51125
51723
|
</mat-form-field>
|
|
51126
51724
|
<mat-form-field appearance="outline">
|
|
51127
51725
|
<mat-label>{{ tx('columns.renderer.microVisualization.fallbackText', 'Accessible fallback text') }}</mat-label>
|
|
51128
51726
|
<input matInput [value]="getRendererProp('microVisualization','visualization.fallbackText') || ''" (input)="setMicroVisualizationProp('fallbackText', $any($event.target).value)" />
|
|
51129
51727
|
</mat-form-field>
|
|
51728
|
+
<div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
|
|
51729
|
+
{{ tx('columns.renderer.microVisualization.tone.precedenceHint', 'In Automatic mode, color is resolved from threshold bands or value sign. A fixed tone overrides conditional bands.') }}
|
|
51730
|
+
</div>
|
|
51731
|
+
@if (isMicroVisualizationThresholdsSupported()) {
|
|
51732
|
+
<div
|
|
51733
|
+
data-testid="micro-viz-thresholds-section"
|
|
51734
|
+
style="grid-column: 1/-1; display: grid; gap: 10px; padding: 12px; border: 1px solid var(--md-sys-color-outline-variant); border-radius: 8px;"
|
|
51735
|
+
>
|
|
51736
|
+
<div style="display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap;">
|
|
51737
|
+
<div>
|
|
51738
|
+
<div style="font-weight: 600;">
|
|
51739
|
+
{{ tx('columns.renderer.microVisualization.thresholds.title', 'Color bands (thresholds)') }}
|
|
51740
|
+
</div>
|
|
51741
|
+
<div class="renderer-hint" style="opacity: .78;">
|
|
51742
|
+
{{ tx('columns.renderer.microVisualization.thresholds.description', 'Evaluates top-to-bottom (first matching band wins). Both min and max bounds are inclusive (min <= value <= max).') }}
|
|
51743
|
+
</div>
|
|
51744
|
+
</div>
|
|
51745
|
+
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
|
51746
|
+
<button
|
|
51747
|
+
mat-stroked-button
|
|
51748
|
+
type="button"
|
|
51749
|
+
data-testid="micro-viz-add-threshold"
|
|
51750
|
+
(click)="addMicroVisualizationThreshold()"
|
|
51751
|
+
>
|
|
51752
|
+
<mat-icon>add</mat-icon>
|
|
51753
|
+
{{ tx('columns.renderer.microVisualization.thresholds.add', 'Add threshold') }}
|
|
51754
|
+
</button>
|
|
51755
|
+
<button
|
|
51756
|
+
mat-stroked-button
|
|
51757
|
+
type="button"
|
|
51758
|
+
data-testid="micro-viz-preset-thresholds"
|
|
51759
|
+
(click)="applyDefaultMicroVisualizationThresholds()"
|
|
51760
|
+
>
|
|
51761
|
+
<mat-icon>traffic</mat-icon>
|
|
51762
|
+
{{ tx('columns.renderer.microVisualization.thresholds.preset', 'Traffic-light preset (70+ / 40–69 / ≤39)') }}
|
|
51763
|
+
</button>
|
|
51764
|
+
</div>
|
|
51765
|
+
</div>
|
|
51766
|
+
@if (!getMicroVisualizationThresholds().length) {
|
|
51767
|
+
<div class="renderer-hint" style="opacity: .75;">
|
|
51768
|
+
{{ tx('columns.renderer.microVisualization.thresholds.empty', 'No threshold bands configured. Add bands or apply the traffic-light preset to color values automatically.') }}
|
|
51769
|
+
</div>
|
|
51770
|
+
}
|
|
51771
|
+
@for (threshold of getMicroVisualizationThresholds(); track $index) {
|
|
51772
|
+
<div
|
|
51773
|
+
data-testid="micro-viz-threshold-row"
|
|
51774
|
+
style="display: grid; grid-template-columns: minmax(110px, 1fr) minmax(110px, 1fr) minmax(140px, 1fr) auto; gap: 8px; align-items: center;"
|
|
51775
|
+
>
|
|
51776
|
+
<mat-form-field appearance="outline">
|
|
51777
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.min', 'Min (inclusive)') }}</mat-label>
|
|
51778
|
+
<input
|
|
51779
|
+
matInput
|
|
51780
|
+
type="number"
|
|
51781
|
+
data-testid="micro-viz-threshold-min"
|
|
51782
|
+
[value]="threshold.min ?? ''"
|
|
51783
|
+
(input)="setMicroVisualizationThresholdNumber($index, 'min', $any($event.target).value)"
|
|
51784
|
+
/>
|
|
51785
|
+
</mat-form-field>
|
|
51786
|
+
<mat-form-field appearance="outline">
|
|
51787
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.max', 'Max (inclusive)') }}</mat-label>
|
|
51788
|
+
<input
|
|
51789
|
+
matInput
|
|
51790
|
+
type="number"
|
|
51791
|
+
data-testid="micro-viz-threshold-max"
|
|
51792
|
+
[value]="threshold.max ?? ''"
|
|
51793
|
+
(input)="setMicroVisualizationThresholdNumber($index, 'max', $any($event.target).value)"
|
|
51794
|
+
/>
|
|
51795
|
+
</mat-form-field>
|
|
51796
|
+
<mat-form-field appearance="outline">
|
|
51797
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.tone', 'Band tone') }}</mat-label>
|
|
51798
|
+
<mat-select
|
|
51799
|
+
data-testid="micro-viz-threshold-tone"
|
|
51800
|
+
[ngModel]="threshold.tone || 'info'"
|
|
51801
|
+
[ngModelOptions]="{standalone: true}"
|
|
51802
|
+
(ngModelChange)="setMicroVisualizationThresholdTone($index, $event)"
|
|
51803
|
+
>
|
|
51804
|
+
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
51805
|
+
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
51806
|
+
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
51807
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
51808
|
+
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
51809
|
+
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
51810
|
+
</mat-select>
|
|
51811
|
+
</mat-form-field>
|
|
51812
|
+
<div style="display: flex; gap: 4px; align-items: center;">
|
|
51813
|
+
<button
|
|
51814
|
+
praxisIconButton="arrow_upward"
|
|
51815
|
+
size="dense"
|
|
51816
|
+
type="button"
|
|
51817
|
+
data-testid="micro-viz-threshold-up"
|
|
51818
|
+
[disabled]="$index === 0"
|
|
51819
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move threshold up')"
|
|
51820
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move threshold up')"
|
|
51821
|
+
(click)="moveMicroVisualizationThreshold($index, -1)"
|
|
51822
|
+
></button>
|
|
51823
|
+
<button
|
|
51824
|
+
praxisIconButton="arrow_downward"
|
|
51825
|
+
size="dense"
|
|
51826
|
+
type="button"
|
|
51827
|
+
data-testid="micro-viz-threshold-down"
|
|
51828
|
+
[disabled]="$index === getMicroVisualizationThresholds().length - 1"
|
|
51829
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move threshold down')"
|
|
51830
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move threshold down')"
|
|
51831
|
+
(click)="moveMicroVisualizationThreshold($index, 1)"
|
|
51832
|
+
></button>
|
|
51833
|
+
<button
|
|
51834
|
+
praxisIconButton="delete_outline"
|
|
51835
|
+
size="dense"
|
|
51836
|
+
type="button"
|
|
51837
|
+
data-testid="micro-viz-threshold-remove"
|
|
51838
|
+
[matTooltip]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove threshold')"
|
|
51839
|
+
[attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove threshold')"
|
|
51840
|
+
(click)="removeMicroVisualizationThreshold($index)"
|
|
51841
|
+
></button>
|
|
51842
|
+
</div>
|
|
51843
|
+
</div>
|
|
51844
|
+
}
|
|
51845
|
+
@if (isMicroVisualizationValueKind()) {
|
|
51846
|
+
<mat-form-field appearance="outline">
|
|
51847
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.sampleValues', 'Preview sample values (comma-separated)') }}</mat-label>
|
|
51848
|
+
<input
|
|
51849
|
+
matInput
|
|
51850
|
+
data-testid="micro-viz-sample-values-input"
|
|
51851
|
+
[value]="microVisualizationSampleValuesText"
|
|
51852
|
+
(input)="setMicroVisualizationSampleValuesText($any($event.target).value)"
|
|
51853
|
+
/>
|
|
51854
|
+
</mat-form-field>
|
|
51855
|
+
<div
|
|
51856
|
+
data-testid="micro-viz-sample-preview"
|
|
51857
|
+
style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center;"
|
|
51858
|
+
>
|
|
51859
|
+
@for (sampleVal of getMicroVisualizationSampleValues(); track $index) {
|
|
51860
|
+
<span
|
|
51861
|
+
class="pfx-micro-viz-cell"
|
|
51862
|
+
[attr.data-sample-value]="sampleVal"
|
|
51863
|
+
[innerHTML]="getPreviewMicroVisualizationHtmlForValue(sampleVal)"
|
|
51864
|
+
></span>
|
|
51865
|
+
}
|
|
51866
|
+
</div>
|
|
51867
|
+
}
|
|
51868
|
+
</div>
|
|
51869
|
+
}
|
|
51130
51870
|
<div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
|
|
51131
51871
|
{{ tx('columns.renderer.microVisualization.hint', 'Use a value for indicators, points for trends, segments for stacked bars, and items for process flows. The table keeps the visual compact and exposes fallback text to assistive technology.') }}
|
|
51132
51872
|
</div>
|
|
@@ -52027,14 +52767,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
52027
52767
|
}
|
|
52028
52768
|
<mat-form-field appearance="outline">
|
|
52029
52769
|
<mat-label>{{ tx('columns.renderer.microVisualization.tone', 'Tone') }}</mat-label>
|
|
52030
|
-
<mat-select [ngModel]="getOverrideMicroVisualizationProp('tone') || '
|
|
52770
|
+
<mat-select [ngModel]="getOverrideMicroVisualizationProp('tone') || ''" [ngModelOptions]="{standalone:true}" (ngModelChange)="setOverrideMicroVisualizationProp('tone', $event || undefined)">
|
|
52771
|
+
<mat-option value="">{{ tx('columns.renderer.microVisualization.tone.auto', 'Automatic (thresholds / default)') }}</mat-option>
|
|
52031
52772
|
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
52032
52773
|
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
52033
52774
|
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
52034
52775
|
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
52035
52776
|
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
52777
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
52036
52778
|
</mat-select>
|
|
52779
|
+
<mat-hint>{{ tx('columns.renderer.microVisualization.tone.precedenceHint', 'Fixed tone overrides thresholds. Choose Automatic to let color bands control the tone.') }}</mat-hint>
|
|
52037
52780
|
</mat-form-field>
|
|
52781
|
+
@if (isOverrideMicroVisualizationThresholdsSupported()) {
|
|
52782
|
+
<div class="micro-viz-thresholds-section" data-testid="override-micro-viz-thresholds-section">
|
|
52783
|
+
<div class="compose-header">
|
|
52784
|
+
<div>
|
|
52785
|
+
<div class="section-subtitle">{{ tx('columns.renderer.microVisualization.thresholds.title', 'Color bands (thresholds)') }}</div>
|
|
52786
|
+
<div class="field-hint">{{ tx('columns.renderer.microVisualization.thresholds.hint', 'First matching band wins (min <= value <= max). Leave min or max empty for open-ended ranges.') }}</div>
|
|
52787
|
+
</div>
|
|
52788
|
+
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
52789
|
+
<button mat-stroked-button type="button" data-testid="override-micro-viz-preset-thresholds" (click)="applyDefaultOverrideMicroVisualizationThresholds()">
|
|
52790
|
+
<mat-icon>palette</mat-icon>
|
|
52791
|
+
{{ tx('columns.renderer.microVisualization.thresholds.applyPreset', 'Traffic-light preset') }}
|
|
52792
|
+
</button>
|
|
52793
|
+
<button mat-stroked-button type="button" data-testid="override-micro-viz-add-threshold" (click)="addOverrideMicroVisualizationThreshold()">
|
|
52794
|
+
<mat-icon>add</mat-icon>
|
|
52795
|
+
{{ tx('columns.renderer.microVisualization.thresholds.add', 'Add band') }}
|
|
52796
|
+
</button>
|
|
52797
|
+
</div>
|
|
52798
|
+
</div>
|
|
52799
|
+
@if (getOverrideMicroVisualizationProp('tone') && getOverrideMicroVisualizationThresholds().length > 0) {
|
|
52800
|
+
<div class="field-hint micro-viz-guidance is-conditional">
|
|
52801
|
+
{{ tx('columns.renderer.microVisualization.thresholds.overriddenByToneWarning', 'A fixed tone is selected above and will override these color bands. Switch Tone to Automatic so thresholds take effect.') }}
|
|
52802
|
+
</div>
|
|
52803
|
+
}
|
|
52804
|
+
@if (getOverrideMicroVisualizationThresholds().length === 0) {
|
|
52805
|
+
<div class="field-hint">{{ tx('columns.renderer.microVisualization.thresholds.empty', 'No color bands configured.') }}</div>
|
|
52806
|
+
}
|
|
52807
|
+
@for (threshold of getOverrideMicroVisualizationThresholds(); track $index; let idx = $index) {
|
|
52808
|
+
<div class="form-row three-columns micro-viz-threshold-row" [attr.data-testid]="'override-micro-viz-threshold-row-' + idx">
|
|
52809
|
+
<mat-form-field appearance="outline">
|
|
52810
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.min', 'Min') }}</mat-label>
|
|
52811
|
+
<input matInput type="number" [value]="threshold.min ?? ''" (input)="setOverrideMicroVisualizationThresholdNumber(idx, 'min', $any($event.target).value)" />
|
|
52812
|
+
</mat-form-field>
|
|
52813
|
+
<mat-form-field appearance="outline">
|
|
52814
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.max', 'Max') }}</mat-label>
|
|
52815
|
+
<input matInput type="number" [value]="threshold.max ?? ''" (input)="setOverrideMicroVisualizationThresholdNumber(idx, 'max', $any($event.target).value)" />
|
|
52816
|
+
</mat-form-field>
|
|
52817
|
+
<div style="display:flex; gap:6px; align-items:flex-start;">
|
|
52818
|
+
<mat-form-field appearance="outline" style="flex:1;">
|
|
52819
|
+
<mat-label>{{ tx('columns.renderer.microVisualization.thresholds.tone', 'Band tone') }}</mat-label>
|
|
52820
|
+
<mat-select [ngModel]="threshold.tone || 'neutral'" [ngModelOptions]="{standalone:true}" (ngModelChange)="setOverrideMicroVisualizationThresholdTone(idx, $event)">
|
|
52821
|
+
<mat-option value="neutral">{{ tx('columns.renderer.microVisualization.tone.neutral', 'Neutral') }}</mat-option>
|
|
52822
|
+
<mat-option value="info">{{ tx('columns.renderer.microVisualization.tone.info', 'Info') }}</mat-option>
|
|
52823
|
+
<mat-option value="success">{{ tx('columns.renderer.microVisualization.tone.success', 'Success') }}</mat-option>
|
|
52824
|
+
<mat-option value="warning">{{ tx('columns.renderer.microVisualization.tone.warning', 'Warning') }}</mat-option>
|
|
52825
|
+
<mat-option value="danger">{{ tx('columns.renderer.microVisualization.tone.danger', 'Danger') }}</mat-option>
|
|
52826
|
+
<mat-option value="critical">{{ tx('columns.renderer.microVisualization.tone.critical', 'Critical') }}</mat-option>
|
|
52827
|
+
</mat-select>
|
|
52828
|
+
</mat-form-field>
|
|
52829
|
+
<button mat-icon-button type="button" (click)="moveOverrideMicroVisualizationThreshold(idx, -1)" [disabled]="idx === 0" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveUp', 'Move band up')">
|
|
52830
|
+
<mat-icon>arrow_upward</mat-icon>
|
|
52831
|
+
</button>
|
|
52832
|
+
<button mat-icon-button type="button" (click)="moveOverrideMicroVisualizationThreshold(idx, 1)" [disabled]="idx === getOverrideMicroVisualizationThresholds().length - 1" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.moveDown', 'Move band down')">
|
|
52833
|
+
<mat-icon>arrow_downward</mat-icon>
|
|
52834
|
+
</button>
|
|
52835
|
+
<button mat-icon-button type="button" color="warn" (click)="removeOverrideMicroVisualizationThreshold(idx)" [attr.aria-label]="tx('columns.renderer.microVisualization.thresholds.remove', 'Remove band')">
|
|
52836
|
+
<mat-icon>delete</mat-icon>
|
|
52837
|
+
</button>
|
|
52838
|
+
</div>
|
|
52839
|
+
</div>
|
|
52840
|
+
}
|
|
52841
|
+
</div>
|
|
52842
|
+
}
|
|
52038
52843
|
<mat-form-field appearance="outline">
|
|
52039
52844
|
<mat-label>{{ tx('columns.renderer.microVisualization.fallbackText', 'Accessible fallback text') }}</mat-label>
|
|
52040
52845
|
<input matInput [value]="getOverrideMicroVisualizationProp('fallbackText') || ''" (input)="setOverrideMicroVisualizationProp('fallbackText', $any($event.target).value)" />
|