@praxisui/list 10.0.0-rc.36 → 10.0.0-rc.38
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/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-list.mjs +945 -82
- package/package.json +6 -6
- package/types/praxisui-list.d.ts +57 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, Input, ChangeDetectionStrategy, Component, LOCALE_ID, EventEmitter, output, CSP_NONCE, ElementRef, Renderer2, DestroyRef, ChangeDetectorRef, effect, Injector, isDevMode, booleanAttribute, Output, signal, Optional, SkipSelf, Inject,
|
|
2
|
+
import { inject, Injectable, Input, ChangeDetectionStrategy, Component, LOCALE_ID, EventEmitter, output, CSP_NONCE, ElementRef, Renderer2, DestroyRef, ChangeDetectorRef, effect, Injector, isDevMode, booleanAttribute, ViewChild, Output, signal, Optional, SkipSelf, Inject, ENVIRONMENT_INITIALIZER, computed } from '@angular/core';
|
|
3
3
|
import { ActivatedRoute } from '@angular/router';
|
|
4
4
|
import * as i1 from '@angular/common';
|
|
5
5
|
import { formatDate, CommonModule } from '@angular/common';
|
|
@@ -11,7 +11,7 @@ import * as i4$1 from '@angular/material/radio';
|
|
|
11
11
|
import { MatRadioModule } from '@angular/material/radio';
|
|
12
12
|
import * as i4 from '@angular/material/icon';
|
|
13
13
|
import { MatIconModule } from '@angular/material/icon';
|
|
14
|
-
import { resolveValuePresentation, LoggerService, GenericCrudService, deepMerge, validateGlobalActionRefs, providePraxisI18n, PraxisIconDirective, ASYNC_CONFIG_STORAGE, ComponentKeyService, PraxisJsonLogicService, PraxisI18nService, PraxisCollectionExportService, GlobalActionService, GLOBAL_DIALOG_SERVICE, ResourceRecordOpenError, ResourceRecordOpenService, assertPraxisCollectionExportArtifact, toTitleCase,
|
|
14
|
+
import { resolveValuePresentation, LoggerService, GenericCrudService, deepMerge, validateGlobalActionRefs, providePraxisI18n, PraxisIconDirective, ASYNC_CONFIG_STORAGE, ComponentKeyService, PraxisJsonLogicService, PraxisI18nService, PraxisCollectionExportService, GlobalActionService, GLOBAL_DIALOG_SERVICE, normalizePraxisDataQueryContext, ResourceRecordOpenError, ResourceRecordOpenService, assertPraxisCollectionExportArtifact, toTitleCase, ResourceQuickConnectComponent, ResourceDiscoveryService, PraxisIconButtonComponent, EmptyStateCardComponent, IconPickerService, SURFACE_OPEN_I18N_NAMESPACE, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, getGlobalActionUiSchema, SurfaceOpenActionEditorComponent, PRAXIS_I18N_CONFIG, providePraxisI18nConfig, SURFACE_OPEN_I18N_CONFIG, ComponentMetadataRegistry, API_URL, LocalStorageAsyncAdapter, LocalStorageConfigService } from '@praxisui/core';
|
|
15
15
|
import * as i2 from '@angular/material/chips';
|
|
16
16
|
import { MatChipsModule } from '@angular/material/chips';
|
|
17
17
|
import { MatDividerModule } from '@angular/material/divider';
|
|
@@ -1482,6 +1482,7 @@ class ExecutiveBadgeComponent {
|
|
|
1482
1482
|
[attr.aria-label]="computedAriaLabel"
|
|
1483
1483
|
>
|
|
1484
1484
|
<praxis-rich-content
|
|
1485
|
+
layout="inline"
|
|
1485
1486
|
rootClassName="badge__content"
|
|
1486
1487
|
[nodes]="contentNodes"
|
|
1487
1488
|
></praxis-rich-content>
|
|
@@ -1498,6 +1499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1498
1499
|
[attr.aria-label]="computedAriaLabel"
|
|
1499
1500
|
>
|
|
1500
1501
|
<praxis-rich-content
|
|
1502
|
+
layout="inline"
|
|
1501
1503
|
rootClassName="badge__content"
|
|
1502
1504
|
[nodes]="contentNodes"
|
|
1503
1505
|
></praxis-rich-content>
|
|
@@ -1646,6 +1648,7 @@ class ExecutiveAlertsComponent {
|
|
|
1646
1648
|
>
|
|
1647
1649
|
<span class="alert-content" aria-hidden="true">
|
|
1648
1650
|
<praxis-rich-content
|
|
1651
|
+
layout="inline"
|
|
1649
1652
|
rootClassName="alert-content__nodes"
|
|
1650
1653
|
[nodes]="alertContentNodes(alert)"
|
|
1651
1654
|
></praxis-rich-content>
|
|
@@ -1677,6 +1680,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1677
1680
|
>
|
|
1678
1681
|
<span class="alert-content" aria-hidden="true">
|
|
1679
1682
|
<praxis-rich-content
|
|
1683
|
+
layout="inline"
|
|
1680
1684
|
rootClassName="alert-content__nodes"
|
|
1681
1685
|
[nodes]="alertContentNodes(alert)"
|
|
1682
1686
|
></praxis-rich-content>
|
|
@@ -1768,6 +1772,7 @@ class ExecutiveOwnerComponent {
|
|
|
1768
1772
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: ExecutiveOwnerComponent, isStandalone: true, selector: "praxis-executive-owner", inputs: { name: "name" }, ngImport: i0, template: `
|
|
1769
1773
|
<div class="owner">
|
|
1770
1774
|
<praxis-rich-content
|
|
1775
|
+
layout="inline"
|
|
1771
1776
|
rootClassName="owner__content"
|
|
1772
1777
|
[nodes]="ownerNodes"
|
|
1773
1778
|
></praxis-rich-content>
|
|
@@ -1779,6 +1784,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1779
1784
|
args: [{ selector: 'praxis-executive-owner', standalone: true, imports: [PraxisRichContent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1780
1785
|
<div class="owner">
|
|
1781
1786
|
<praxis-rich-content
|
|
1787
|
+
layout="inline"
|
|
1782
1788
|
rootClassName="owner__content"
|
|
1783
1789
|
[nodes]="ownerNodes"
|
|
1784
1790
|
></praxis-rich-content>
|
|
@@ -5734,7 +5740,20 @@ function inferTemplatingFromSchema(cfg, fieldNames) {
|
|
|
5734
5740
|
if (!needsPrimary)
|
|
5735
5741
|
return cfg; // respect user config
|
|
5736
5742
|
const pickBy = (preds, accept = () => true) => names.find((n) => preds.some((p) => p.test(String(n))) && accept(n)) || undefined;
|
|
5737
|
-
const primaryName = pickBy([
|
|
5743
|
+
const primaryName = pickBy([
|
|
5744
|
+
/nomeCompleto/i,
|
|
5745
|
+
/fullName/i,
|
|
5746
|
+
/^nome$/i,
|
|
5747
|
+
/^name$/i,
|
|
5748
|
+
/^nome[A-Z]/,
|
|
5749
|
+
/^title$/i,
|
|
5750
|
+
/^titulo$/i,
|
|
5751
|
+
/title/i,
|
|
5752
|
+
/titulo/i,
|
|
5753
|
+
/label/i,
|
|
5754
|
+
]) ||
|
|
5755
|
+
names.find(isReadableBusinessField) ||
|
|
5756
|
+
names[0];
|
|
5738
5757
|
const avatarName = pickBy([
|
|
5739
5758
|
/avatar/i,
|
|
5740
5759
|
/foto/i,
|
|
@@ -5747,10 +5766,10 @@ function inferTemplatingFromSchema(cfg, fieldNames) {
|
|
|
5747
5766
|
const emailName = pickBy([/email/i, /e-mail/i]);
|
|
5748
5767
|
const phoneName = pickBy([/telefone/i, /phone/i, /celular/i, /mobile/i, /whats/i]);
|
|
5749
5768
|
const cpfName = pickBy([/^cpf$/i, /documento/i, /document/i, /taxId/i]);
|
|
5750
|
-
const roleName = pickBy([/cargoNome/i, /roleName/i, /funcaoNome/i, /funçãoNome/i, /positionName/i]) ||
|
|
5751
|
-
pickBy([/cargo/i, /role/i, /funcao/i, /função/i, /position/i], isReadableBusinessField);
|
|
5752
|
-
const departmentName = pickBy([/departamentoNome/i, /departmentName/i, /areaNome/i, /setorNome/i, /teamName/i]) ||
|
|
5753
|
-
pickBy([/departamento/i, /department/i, /area/i, /setor/i, /team/i], isReadableBusinessField);
|
|
5769
|
+
const roleName = pickBy([/cargoNome/i, /roleName/i, /funcaoNome/i, /funçãoNome/i, /positionName/i], (n) => n !== primaryName) ||
|
|
5770
|
+
pickBy([/cargo/i, /role/i, /funcao/i, /função/i, /position/i], (n) => n !== primaryName && isReadableBusinessField(n));
|
|
5771
|
+
const departmentName = pickBy([/departamentoNome/i, /departmentName/i, /areaNome/i, /setorNome/i, /teamName/i], (n) => n !== primaryName) ||
|
|
5772
|
+
pickBy([/departamento/i, /department/i, /area/i, /setor/i, /team/i], (n) => n !== primaryName && isReadableBusinessField(n));
|
|
5754
5773
|
const descriptionName = names.find((n) => n !== primaryName && /(desc|descricao|descrição|resumo|summary)/i.test(n));
|
|
5755
5774
|
const secondaryFields = [phoneName, emailName].filter(Boolean);
|
|
5756
5775
|
const fallbackSecondaryFields = [cpfName, emailName].filter(Boolean);
|
|
@@ -5759,7 +5778,16 @@ function inferTemplatingFromSchema(cfg, fieldNames) {
|
|
|
5759
5778
|
: fallbackSecondaryFields.length > 1
|
|
5760
5779
|
? undefined
|
|
5761
5780
|
: roleName || departmentName || descriptionName || names.find((n) => n !== primaryName && isDisplayFallbackField(n));
|
|
5762
|
-
const trailingName = pickBy([
|
|
5781
|
+
const trailingName = pickBy([
|
|
5782
|
+
/status/i,
|
|
5783
|
+
/situacao/i,
|
|
5784
|
+
/situação/i,
|
|
5785
|
+
/tag/i,
|
|
5786
|
+
/state/i,
|
|
5787
|
+
/^ativo$/i,
|
|
5788
|
+
/^active$/i,
|
|
5789
|
+
/enabled/i,
|
|
5790
|
+
]);
|
|
5763
5791
|
const trailingIsBoolean = !!trailingName && /(^ativo$|^active$|enabled)/i.test(trailingName);
|
|
5764
5792
|
const newCfg = produce(cfg, (draft) => {
|
|
5765
5793
|
const t = { ...draft.templating };
|
|
@@ -5809,6 +5837,22 @@ function inferTemplatingFromSchema(cfg, fieldNames) {
|
|
|
5809
5837
|
false: 'warn',
|
|
5810
5838
|
};
|
|
5811
5839
|
}
|
|
5840
|
+
const usesIdentityRowSlot = Array.isArray(draft.layout?.rowLayout?.columns) &&
|
|
5841
|
+
draft.layout.rowLayout.columns.some((col) => col?.slot === 'identity');
|
|
5842
|
+
if (usesIdentityRowSlot && !t.identity && t.primary) {
|
|
5843
|
+
t.identity = t.secondary
|
|
5844
|
+
? {
|
|
5845
|
+
type: 'compose',
|
|
5846
|
+
props: {
|
|
5847
|
+
compose: {
|
|
5848
|
+
direction: 'column',
|
|
5849
|
+
gap: '2px',
|
|
5850
|
+
items: [t.primary, t.secondary],
|
|
5851
|
+
},
|
|
5852
|
+
},
|
|
5853
|
+
}
|
|
5854
|
+
: t.primary;
|
|
5855
|
+
}
|
|
5812
5856
|
draft.templating = t;
|
|
5813
5857
|
});
|
|
5814
5858
|
return newCfg;
|
|
@@ -5833,7 +5877,7 @@ function makeCompose(fields) {
|
|
|
5833
5877
|
}
|
|
5834
5878
|
function isDisplayFallbackField(field) {
|
|
5835
5879
|
return isReadableBusinessField(field) &&
|
|
5836
|
-
!/(idade|age|ativo|active|enabled|status|state|tag|avatar|foto|photo|image|imagem|picture)/i.test(field);
|
|
5880
|
+
!/(idade|age|ativo|active|enabled|status|situacao|situação|state|tag|avatar|foto|photo|image|imagem|picture)/i.test(field);
|
|
5837
5881
|
}
|
|
5838
5882
|
function isReadableBusinessField(field) {
|
|
5839
5883
|
return !/(^id$|Id$|ID$|_id$|-id$)/.test(field);
|
|
@@ -5989,16 +6033,116 @@ function shouldInferTemplatingFromSchema(config, schemaFieldNames) {
|
|
|
5989
6033
|
}
|
|
5990
6034
|
function hasUngroundedTemplatingSlot(config, schemaFieldNames) {
|
|
5991
6035
|
const slots = config.templating || {};
|
|
5992
|
-
return
|
|
6036
|
+
return ROW_LAYOUT_TEMPLATE_SLOTS.some((slot) => shouldDropTemplatingSlot(slots[slot], schemaFieldNames, slot));
|
|
5993
6037
|
}
|
|
5994
6038
|
function removeUngroundedTemplatingSlots(config, schemaFieldNames) {
|
|
5995
6039
|
const templating = { ...(config.templating || {}) };
|
|
5996
|
-
|
|
6040
|
+
const droppedSlots = new Set();
|
|
6041
|
+
for (const slot of ROW_LAYOUT_TEMPLATE_SLOTS) {
|
|
5997
6042
|
if (shouldDropTemplatingSlot(templating[slot], schemaFieldNames, slot)) {
|
|
5998
6043
|
delete templating[slot];
|
|
6044
|
+
droppedSlots.add(slot);
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
if (droppedSlots.has('trailing') || droppedSlots.has('meta') || droppedSlots.has('leading')) {
|
|
6048
|
+
const hasRemainingChipSlot = ROW_LAYOUT_TEMPLATE_SLOTS.some((slot) => templating[slot]?.type === 'chip');
|
|
6049
|
+
if (!hasRemainingChipSlot) {
|
|
6050
|
+
delete templating['chipColorMap'];
|
|
6051
|
+
delete templating['chipLabelMap'];
|
|
6052
|
+
}
|
|
6053
|
+
const hasRemainingIconFieldSlot = ROW_LAYOUT_TEMPLATE_SLOTS.some((slot) => templating[slot]?.type === 'icon' &&
|
|
6054
|
+
templateFieldReferences(templating[slot]).length > 0);
|
|
6055
|
+
if (!hasRemainingIconFieldSlot) {
|
|
6056
|
+
delete templating['iconColorMap'];
|
|
5999
6057
|
}
|
|
6000
6058
|
}
|
|
6001
|
-
|
|
6059
|
+
const schemaFields = new Set(schemaFieldNames);
|
|
6060
|
+
let nextUi = config.ui;
|
|
6061
|
+
if (nextUi) {
|
|
6062
|
+
let uiMutated = false;
|
|
6063
|
+
const clonedUi = { ...nextUi };
|
|
6064
|
+
if (typeof clonedUi.searchField === 'string' &&
|
|
6065
|
+
clonedUi.searchField.trim().length > 0 &&
|
|
6066
|
+
!schemaFields.has(clonedUi.searchField.trim())) {
|
|
6067
|
+
delete clonedUi.searchField;
|
|
6068
|
+
uiMutated = true;
|
|
6069
|
+
}
|
|
6070
|
+
if (Array.isArray(clonedUi.sortOptions)) {
|
|
6071
|
+
const filteredSortOptions = clonedUi.sortOptions.filter((opt) => {
|
|
6072
|
+
const rawField = String(typeof opt === 'string' ? opt : (opt?.field ?? opt?.value ?? ''))
|
|
6073
|
+
.split(/[,:]/)[0]
|
|
6074
|
+
.trim();
|
|
6075
|
+
return !rawField || schemaFields.has(rawField);
|
|
6076
|
+
});
|
|
6077
|
+
if (filteredSortOptions.length !== clonedUi.sortOptions.length) {
|
|
6078
|
+
clonedUi.sortOptions = filteredSortOptions;
|
|
6079
|
+
uiMutated = true;
|
|
6080
|
+
}
|
|
6081
|
+
}
|
|
6082
|
+
if (uiMutated) {
|
|
6083
|
+
nextUi = clonedUi;
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
6086
|
+
let nextDataSource = config.dataSource;
|
|
6087
|
+
if (Array.isArray(nextDataSource?.sort)) {
|
|
6088
|
+
const filteredSort = nextDataSource.sort.filter((entry) => {
|
|
6089
|
+
const rawField = typeof entry === 'string'
|
|
6090
|
+
? entry.split(/[,:]/)[0].trim()
|
|
6091
|
+
: String(entry?.field ?? '').trim();
|
|
6092
|
+
return !rawField || schemaFields.has(rawField);
|
|
6093
|
+
});
|
|
6094
|
+
if (filteredSort.length !== nextDataSource.sort.length) {
|
|
6095
|
+
const clonedDataSource = { ...nextDataSource };
|
|
6096
|
+
if (filteredSort.length > 0) {
|
|
6097
|
+
clonedDataSource.sort = filteredSort;
|
|
6098
|
+
}
|
|
6099
|
+
else {
|
|
6100
|
+
delete clonedDataSource.sort;
|
|
6101
|
+
}
|
|
6102
|
+
nextDataSource = clonedDataSource;
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
6105
|
+
if (Array.isArray(nextDataSource?.query?.sort)) {
|
|
6106
|
+
const currentQuerySort = nextDataSource.query.sort;
|
|
6107
|
+
const filteredQuerySort = currentQuerySort.filter((entry) => {
|
|
6108
|
+
const rawField = typeof entry === 'string'
|
|
6109
|
+
? entry.split(/[,:]/)[0].trim()
|
|
6110
|
+
: String(entry?.field ?? '').trim();
|
|
6111
|
+
return !rawField || schemaFields.has(rawField);
|
|
6112
|
+
});
|
|
6113
|
+
if (filteredQuerySort.length !== currentQuerySort.length) {
|
|
6114
|
+
const clonedQuery = { ...nextDataSource.query };
|
|
6115
|
+
if (filteredQuerySort.length > 0) {
|
|
6116
|
+
clonedQuery['sort'] = filteredQuerySort;
|
|
6117
|
+
}
|
|
6118
|
+
else {
|
|
6119
|
+
delete clonedQuery['sort'];
|
|
6120
|
+
}
|
|
6121
|
+
const clonedDataSource = { ...nextDataSource };
|
|
6122
|
+
if (Object.keys(clonedQuery).length > 0) {
|
|
6123
|
+
clonedDataSource.query = clonedQuery;
|
|
6124
|
+
}
|
|
6125
|
+
else {
|
|
6126
|
+
delete clonedDataSource.query;
|
|
6127
|
+
}
|
|
6128
|
+
nextDataSource = clonedDataSource;
|
|
6129
|
+
}
|
|
6130
|
+
}
|
|
6131
|
+
let nextSelection = config.selection;
|
|
6132
|
+
if (typeof nextSelection?.compareBy === 'string' &&
|
|
6133
|
+
nextSelection.compareBy.trim().length > 0 &&
|
|
6134
|
+
!schemaFields.has(nextSelection.compareBy.trim())) {
|
|
6135
|
+
const clonedSelection = { ...nextSelection };
|
|
6136
|
+
delete clonedSelection.compareBy;
|
|
6137
|
+
nextSelection = clonedSelection;
|
|
6138
|
+
}
|
|
6139
|
+
return {
|
|
6140
|
+
...config,
|
|
6141
|
+
templating,
|
|
6142
|
+
...(nextUi !== config.ui ? { ui: nextUi } : {}),
|
|
6143
|
+
...(nextDataSource !== config.dataSource ? { dataSource: nextDataSource } : {}),
|
|
6144
|
+
...(nextSelection !== config.selection ? { selection: nextSelection } : {}),
|
|
6145
|
+
};
|
|
6002
6146
|
}
|
|
6003
6147
|
function shouldDropTemplatingSlot(template, schemaFieldNames, slot) {
|
|
6004
6148
|
if (!template)
|
|
@@ -7331,7 +7475,14 @@ const PRAXIS_LIST_EN_US = {
|
|
|
7331
7475
|
collapseDetails: 'Collapse details',
|
|
7332
7476
|
itemDetails: 'Item details',
|
|
7333
7477
|
emptyState: 'No items available',
|
|
7478
|
+
emptyStateDescription: 'There are no items to display right now.',
|
|
7479
|
+
emptyStateFilteredTitle: 'No results found',
|
|
7480
|
+
emptyStateFilteredDescription: 'Review the active filters or adjust the search term.',
|
|
7481
|
+
emptyStateClearSearchAction: 'Clear search',
|
|
7482
|
+
emptyStateConnectResourceTitle: 'Choose the list resource',
|
|
7334
7483
|
emptyStateConnectResource: 'Connect this list to a resource to load items.',
|
|
7484
|
+
emptyStateConnectResourceAction: 'Select resource',
|
|
7485
|
+
emptyStateConfigureAction: 'Configure list',
|
|
7335
7486
|
recordOpenUnavailable: 'Unable to open details for this item.',
|
|
7336
7487
|
'selection.ariaLabel': 'Selectable list',
|
|
7337
7488
|
'selection.selectItem': 'Select item',
|
|
@@ -7724,7 +7875,14 @@ const PRAXIS_LIST_PT_BR = {
|
|
|
7724
7875
|
collapseDetails: 'Recolher detalhes',
|
|
7725
7876
|
itemDetails: 'Detalhes do item',
|
|
7726
7877
|
emptyState: 'Nenhum item disponível',
|
|
7878
|
+
emptyStateDescription: 'Não há itens para exibir neste momento.',
|
|
7879
|
+
emptyStateFilteredTitle: 'Nenhum resultado encontrado',
|
|
7880
|
+
emptyStateFilteredDescription: 'Revise os filtros ou ajuste o termo de busca.',
|
|
7881
|
+
emptyStateClearSearchAction: 'Limpar busca',
|
|
7882
|
+
emptyStateConnectResourceTitle: 'Escolha o recurso da lista',
|
|
7727
7883
|
emptyStateConnectResource: 'Conecte a lista a um recurso para carregar os itens.',
|
|
7884
|
+
emptyStateConnectResourceAction: 'Selecionar recurso',
|
|
7885
|
+
emptyStateConfigureAction: 'Configurar lista',
|
|
7728
7886
|
recordOpenUnavailable: 'Não foi possível abrir os detalhes deste item.',
|
|
7729
7887
|
'selection.ariaLabel': 'Lista selecionável',
|
|
7730
7888
|
'selection.selectItem': 'Selecionar item',
|
|
@@ -8249,14 +8407,17 @@ class PraxisListMetricComponent {
|
|
|
8249
8407
|
class="p-list-metric__icon"
|
|
8250
8408
|
[style.cssText]="metric?.iconStyle || ''"
|
|
8251
8409
|
>
|
|
8252
|
-
<praxis-rich-content
|
|
8410
|
+
<praxis-rich-content
|
|
8411
|
+
layout="inline"
|
|
8412
|
+
[nodes]="leftIconNodes()"
|
|
8413
|
+
></praxis-rich-content>
|
|
8253
8414
|
</span>
|
|
8254
8415
|
}
|
|
8255
8416
|
|
|
8256
8417
|
<div class="p-list-metric__content">
|
|
8257
8418
|
<div class="p-list-metric__value-row">
|
|
8258
8419
|
<praxis-rich-content
|
|
8259
|
-
|
|
8420
|
+
layout="inline"
|
|
8260
8421
|
rootClassName="p-list-metric__value-row-content"
|
|
8261
8422
|
[nodes]="valueRowNodes()"
|
|
8262
8423
|
></praxis-rich-content>
|
|
@@ -8267,11 +8428,17 @@ class PraxisListMetricComponent {
|
|
|
8267
8428
|
metric?.caption &&
|
|
8268
8429
|
metric?.captionPosition !== 'below-progress'
|
|
8269
8430
|
) {
|
|
8270
|
-
<praxis-rich-content
|
|
8431
|
+
<praxis-rich-content
|
|
8432
|
+
layout="inline"
|
|
8433
|
+
[nodes]="captionNodes()"
|
|
8434
|
+
></praxis-rich-content>
|
|
8271
8435
|
}
|
|
8272
8436
|
|
|
8273
8437
|
@if (metric?.subcaption) {
|
|
8274
|
-
<praxis-rich-content
|
|
8438
|
+
<praxis-rich-content
|
|
8439
|
+
layout="inline"
|
|
8440
|
+
[nodes]="subcaptionNodes()"
|
|
8441
|
+
></praxis-rich-content>
|
|
8275
8442
|
}
|
|
8276
8443
|
</div>
|
|
8277
8444
|
|
|
@@ -8280,7 +8447,10 @@ class PraxisListMetricComponent {
|
|
|
8280
8447
|
class="p-list-metric__icon p-list-metric__icon--right"
|
|
8281
8448
|
[style.cssText]="metric?.iconStyle || ''"
|
|
8282
8449
|
>
|
|
8283
|
-
<praxis-rich-content
|
|
8450
|
+
<praxis-rich-content
|
|
8451
|
+
layout="inline"
|
|
8452
|
+
[nodes]="rightIconNodes()"
|
|
8453
|
+
></praxis-rich-content>
|
|
8284
8454
|
</span>
|
|
8285
8455
|
}
|
|
8286
8456
|
</div>
|
|
@@ -8311,10 +8481,14 @@ class PraxisListMetricComponent {
|
|
|
8311
8481
|
metric?.caption &&
|
|
8312
8482
|
metric?.captionPosition === 'below-progress'
|
|
8313
8483
|
) {
|
|
8314
|
-
<praxis-rich-content
|
|
8484
|
+
<praxis-rich-content
|
|
8485
|
+
layout="inline"
|
|
8486
|
+
rootClassName="p-list-metric__below-progress"
|
|
8487
|
+
[nodes]="belowProgressCaptionNodes()"
|
|
8488
|
+
></praxis-rich-content>
|
|
8315
8489
|
}
|
|
8316
8490
|
</div>
|
|
8317
|
-
`, isInline: true, styles: [":host{display:block;min-width:0}.p-list-metric{--p-list-metric-tone: currentColor;--p-list-metric-progress-fill: var( --p-list-metric-tone, var(--p-list-accent) );--p-list-metric-progress-track: color-mix( in srgb, var(--p-list-metric-progress-fill) 18%, transparent );display:grid;gap:4px;min-width:0;color:var(--p-list-metric-tone, inherit)}.p-list-metric--align-start{justify-items:start;text-align:start}.p-list-metric--align-center{justify-items:center;text-align:center}.p-list-metric--align-end{justify-items:end;text-align:end}.p-list-metric--tone-positive{--p-list-metric-tone: var(--p-color-success, #10b981)}.p-list-metric--tone-warning{--p-list-metric-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) )}.p-list-metric--tone-negative{--p-list-metric-tone: var(--md-sys-color-error, #ef4444)}.p-list-metric--tone-neutral{--p-list-metric-tone: var(--p-list-foreground-muted)}.p-list-metric__label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.p-list-metric__main{display:grid;align-items:center;gap:8px;min-width:0}.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto minmax(0,1fr)}.p-list-metric--layout-stacked-center .p-list-metric__main{justify-items:center;text-align:center}.p-list-metric--icon-right .p-list-metric__main{grid-template-columns:minmax(0,1fr) auto}.p-list-metric__icon{display:inline-flex;align-items:center;justify-content:center;color:var(--p-list-metric-tone, inherit)}.p-list-metric__icon--right{order:2}.p-list-metric__icon mat-icon{width:1rem;height:1rem;font-size:1rem}.p-list-metric__content{display:grid;gap:2px;min-width:0}.p-list-metric__value-row{display:flex;align-items:baseline;gap:6px;min-width:0;flex-wrap:wrap;--prx-rich-content-inline-align-items: baseline;--prx-rich-content-inline-flex-wrap: wrap;--prx-rich-content-inline-gap: 6px}.p-list-metric--layout-stacked-center .p-list-metric__value-row{justify-content:center}.p-list-metric__value{font-size:.95rem;font-weight:700;line-height:1.1;min-width:0}.p-list-metric__caption,.p-list-metric__subcaption{font-size:.72rem;line-height:1.2;color:var(--p-list-foreground-muted)}.p-list-metric__caption--inline{display:inline-flex;align-items:center}.p-list-metric__progress{width:100%;height:4px;border-radius:999px;overflow:hidden;background:var(--p-list-metric-progress-track)}.p-list-metric__progress-value{display:block;height:100%;border-radius:inherit;background:var(--p-list-metric-progress-fill)}.p-list-metric__progress--indeterminate{position:relative}.p-list-metric__progress--indeterminate .p-list-metric__progress-value{width:40%!important;animation:p-list-metric-progress 1.2s ease-in-out infinite}@keyframes p-list-metric-progress{0%{transform:translate(-100%)}to{transform:translate(250%)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
|
|
8491
|
+
`, isInline: true, styles: [":host{display:block;min-width:0}.p-list-metric{--p-list-metric-tone: currentColor;--p-list-metric-progress-fill: var( --p-list-metric-tone, var(--p-list-accent) );--p-list-metric-progress-track: color-mix( in srgb, var(--p-list-metric-progress-fill) 18%, transparent );display:grid;gap:4px;min-width:0;color:var(--p-list-metric-tone, inherit)}.p-list-metric--align-start{justify-items:start;text-align:start}.p-list-metric--align-center{justify-items:center;text-align:center}.p-list-metric--align-center .p-list-metric__main{justify-content:center;justify-items:center}.p-list-metric--align-center.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto auto}.p-list-metric--align-center .p-list-metric__content{justify-items:center;text-align:center}.p-list-metric--align-center .p-list-metric__value-row{justify-content:center}.p-list-metric--align-end{justify-items:end;text-align:end}.p-list-metric--align-end .p-list-metric__main{justify-content:end;justify-items:end}.p-list-metric--align-end .p-list-metric__content{justify-items:end;text-align:end}.p-list-metric--align-end .p-list-metric__value-row{justify-content:flex-end}.p-list-metric--tone-positive{--p-list-metric-tone: var(--p-color-success, #10b981)}.p-list-metric--tone-warning{--p-list-metric-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) )}.p-list-metric--tone-negative{--p-list-metric-tone: var(--md-sys-color-error, #ef4444)}.p-list-metric--tone-neutral{--p-list-metric-tone: var(--p-list-foreground-muted)}.p-list-metric__label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.p-list-metric__main{display:grid;align-items:center;gap:8px;min-width:0}.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto minmax(0,1fr)}.p-list-metric--layout-stacked-center .p-list-metric__main{justify-items:center;text-align:center}.p-list-metric--icon-right .p-list-metric__main{grid-template-columns:minmax(0,1fr) auto}.p-list-metric__icon{display:inline-flex;align-items:center;justify-content:center;color:var(--p-list-metric-tone, inherit)}.p-list-metric__icon--right{order:2}.p-list-metric__icon mat-icon{width:1rem;height:1rem;font-size:1rem}.p-list-metric__content{display:grid;gap:2px;min-width:0}.p-list-metric__value-row{display:flex;align-items:baseline;gap:6px;min-width:0;flex-wrap:wrap;--prx-rich-content-inline-align-items: baseline;--prx-rich-content-inline-flex-wrap: wrap;--prx-rich-content-inline-gap: 6px}.p-list-metric--layout-stacked-center .p-list-metric__value-row{justify-content:center}.p-list-metric__value{font-size:.95rem;font-weight:700;line-height:1.1;min-width:0}.p-list-metric__caption,.p-list-metric__subcaption{font-size:.72rem;line-height:1.2;color:var(--p-list-foreground-muted)}.p-list-metric__caption--inline{display:inline-flex;align-items:center}.p-list-metric__progress{width:100%;height:4px;border-radius:999px;overflow:hidden;background:var(--p-list-metric-progress-track)}.p-list-metric__progress-value{display:block;height:100%;border-radius:inherit;background:var(--p-list-metric-progress-fill)}.p-list-metric__progress--indeterminate{position:relative}.p-list-metric__progress--indeterminate .p-list-metric__progress-value{width:40%!important;animation:p-list-metric-progress 1.2s ease-in-out infinite}@keyframes p-list-metric-progress{0%{transform:translate(-100%)}to{transform:translate(250%)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
|
|
8318
8492
|
}
|
|
8319
8493
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisListMetricComponent, decorators: [{
|
|
8320
8494
|
type: Component,
|
|
@@ -8334,14 +8508,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8334
8508
|
class="p-list-metric__icon"
|
|
8335
8509
|
[style.cssText]="metric?.iconStyle || ''"
|
|
8336
8510
|
>
|
|
8337
|
-
<praxis-rich-content
|
|
8511
|
+
<praxis-rich-content
|
|
8512
|
+
layout="inline"
|
|
8513
|
+
[nodes]="leftIconNodes()"
|
|
8514
|
+
></praxis-rich-content>
|
|
8338
8515
|
</span>
|
|
8339
8516
|
}
|
|
8340
8517
|
|
|
8341
8518
|
<div class="p-list-metric__content">
|
|
8342
8519
|
<div class="p-list-metric__value-row">
|
|
8343
8520
|
<praxis-rich-content
|
|
8344
|
-
|
|
8521
|
+
layout="inline"
|
|
8345
8522
|
rootClassName="p-list-metric__value-row-content"
|
|
8346
8523
|
[nodes]="valueRowNodes()"
|
|
8347
8524
|
></praxis-rich-content>
|
|
@@ -8352,11 +8529,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8352
8529
|
metric?.caption &&
|
|
8353
8530
|
metric?.captionPosition !== 'below-progress'
|
|
8354
8531
|
) {
|
|
8355
|
-
<praxis-rich-content
|
|
8532
|
+
<praxis-rich-content
|
|
8533
|
+
layout="inline"
|
|
8534
|
+
[nodes]="captionNodes()"
|
|
8535
|
+
></praxis-rich-content>
|
|
8356
8536
|
}
|
|
8357
8537
|
|
|
8358
8538
|
@if (metric?.subcaption) {
|
|
8359
|
-
<praxis-rich-content
|
|
8539
|
+
<praxis-rich-content
|
|
8540
|
+
layout="inline"
|
|
8541
|
+
[nodes]="subcaptionNodes()"
|
|
8542
|
+
></praxis-rich-content>
|
|
8360
8543
|
}
|
|
8361
8544
|
</div>
|
|
8362
8545
|
|
|
@@ -8365,7 +8548,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8365
8548
|
class="p-list-metric__icon p-list-metric__icon--right"
|
|
8366
8549
|
[style.cssText]="metric?.iconStyle || ''"
|
|
8367
8550
|
>
|
|
8368
|
-
<praxis-rich-content
|
|
8551
|
+
<praxis-rich-content
|
|
8552
|
+
layout="inline"
|
|
8553
|
+
[nodes]="rightIconNodes()"
|
|
8554
|
+
></praxis-rich-content>
|
|
8369
8555
|
</span>
|
|
8370
8556
|
}
|
|
8371
8557
|
</div>
|
|
@@ -8396,10 +8582,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8396
8582
|
metric?.caption &&
|
|
8397
8583
|
metric?.captionPosition === 'below-progress'
|
|
8398
8584
|
) {
|
|
8399
|
-
<praxis-rich-content
|
|
8585
|
+
<praxis-rich-content
|
|
8586
|
+
layout="inline"
|
|
8587
|
+
rootClassName="p-list-metric__below-progress"
|
|
8588
|
+
[nodes]="belowProgressCaptionNodes()"
|
|
8589
|
+
></praxis-rich-content>
|
|
8400
8590
|
}
|
|
8401
8591
|
</div>
|
|
8402
|
-
`, styles: [":host{display:block;min-width:0}.p-list-metric{--p-list-metric-tone: currentColor;--p-list-metric-progress-fill: var( --p-list-metric-tone, var(--p-list-accent) );--p-list-metric-progress-track: color-mix( in srgb, var(--p-list-metric-progress-fill) 18%, transparent );display:grid;gap:4px;min-width:0;color:var(--p-list-metric-tone, inherit)}.p-list-metric--align-start{justify-items:start;text-align:start}.p-list-metric--align-center{justify-items:center;text-align:center}.p-list-metric--align-end{justify-items:end;text-align:end}.p-list-metric--tone-positive{--p-list-metric-tone: var(--p-color-success, #10b981)}.p-list-metric--tone-warning{--p-list-metric-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) )}.p-list-metric--tone-negative{--p-list-metric-tone: var(--md-sys-color-error, #ef4444)}.p-list-metric--tone-neutral{--p-list-metric-tone: var(--p-list-foreground-muted)}.p-list-metric__label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.p-list-metric__main{display:grid;align-items:center;gap:8px;min-width:0}.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto minmax(0,1fr)}.p-list-metric--layout-stacked-center .p-list-metric__main{justify-items:center;text-align:center}.p-list-metric--icon-right .p-list-metric__main{grid-template-columns:minmax(0,1fr) auto}.p-list-metric__icon{display:inline-flex;align-items:center;justify-content:center;color:var(--p-list-metric-tone, inherit)}.p-list-metric__icon--right{order:2}.p-list-metric__icon mat-icon{width:1rem;height:1rem;font-size:1rem}.p-list-metric__content{display:grid;gap:2px;min-width:0}.p-list-metric__value-row{display:flex;align-items:baseline;gap:6px;min-width:0;flex-wrap:wrap;--prx-rich-content-inline-align-items: baseline;--prx-rich-content-inline-flex-wrap: wrap;--prx-rich-content-inline-gap: 6px}.p-list-metric--layout-stacked-center .p-list-metric__value-row{justify-content:center}.p-list-metric__value{font-size:.95rem;font-weight:700;line-height:1.1;min-width:0}.p-list-metric__caption,.p-list-metric__subcaption{font-size:.72rem;line-height:1.2;color:var(--p-list-foreground-muted)}.p-list-metric__caption--inline{display:inline-flex;align-items:center}.p-list-metric__progress{width:100%;height:4px;border-radius:999px;overflow:hidden;background:var(--p-list-metric-progress-track)}.p-list-metric__progress-value{display:block;height:100%;border-radius:inherit;background:var(--p-list-metric-progress-fill)}.p-list-metric__progress--indeterminate{position:relative}.p-list-metric__progress--indeterminate .p-list-metric__progress-value{width:40%!important;animation:p-list-metric-progress 1.2s ease-in-out infinite}@keyframes p-list-metric-progress{0%{transform:translate(-100%)}to{transform:translate(250%)}}\n"] }]
|
|
8592
|
+
`, styles: [":host{display:block;min-width:0}.p-list-metric{--p-list-metric-tone: currentColor;--p-list-metric-progress-fill: var( --p-list-metric-tone, var(--p-list-accent) );--p-list-metric-progress-track: color-mix( in srgb, var(--p-list-metric-progress-fill) 18%, transparent );display:grid;gap:4px;min-width:0;color:var(--p-list-metric-tone, inherit)}.p-list-metric--align-start{justify-items:start;text-align:start}.p-list-metric--align-center{justify-items:center;text-align:center}.p-list-metric--align-center .p-list-metric__main{justify-content:center;justify-items:center}.p-list-metric--align-center.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto auto}.p-list-metric--align-center .p-list-metric__content{justify-items:center;text-align:center}.p-list-metric--align-center .p-list-metric__value-row{justify-content:center}.p-list-metric--align-end{justify-items:end;text-align:end}.p-list-metric--align-end .p-list-metric__main{justify-content:end;justify-items:end}.p-list-metric--align-end .p-list-metric__content{justify-items:end;text-align:end}.p-list-metric--align-end .p-list-metric__value-row{justify-content:flex-end}.p-list-metric--tone-positive{--p-list-metric-tone: var(--p-color-success, #10b981)}.p-list-metric--tone-warning{--p-list-metric-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) )}.p-list-metric--tone-negative{--p-list-metric-tone: var(--md-sys-color-error, #ef4444)}.p-list-metric--tone-neutral{--p-list-metric-tone: var(--p-list-foreground-muted)}.p-list-metric__label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.p-list-metric__main{display:grid;align-items:center;gap:8px;min-width:0}.p-list-metric--layout-icon-value-caption .p-list-metric__main{grid-template-columns:auto minmax(0,1fr)}.p-list-metric--layout-stacked-center .p-list-metric__main{justify-items:center;text-align:center}.p-list-metric--icon-right .p-list-metric__main{grid-template-columns:minmax(0,1fr) auto}.p-list-metric__icon{display:inline-flex;align-items:center;justify-content:center;color:var(--p-list-metric-tone, inherit)}.p-list-metric__icon--right{order:2}.p-list-metric__icon mat-icon{width:1rem;height:1rem;font-size:1rem}.p-list-metric__content{display:grid;gap:2px;min-width:0}.p-list-metric__value-row{display:flex;align-items:baseline;gap:6px;min-width:0;flex-wrap:wrap;--prx-rich-content-inline-align-items: baseline;--prx-rich-content-inline-flex-wrap: wrap;--prx-rich-content-inline-gap: 6px}.p-list-metric--layout-stacked-center .p-list-metric__value-row{justify-content:center}.p-list-metric__value{font-size:.95rem;font-weight:700;line-height:1.1;min-width:0}.p-list-metric__caption,.p-list-metric__subcaption{font-size:.72rem;line-height:1.2;color:var(--p-list-foreground-muted)}.p-list-metric__caption--inline{display:inline-flex;align-items:center}.p-list-metric__progress{width:100%;height:4px;border-radius:999px;overflow:hidden;background:var(--p-list-metric-progress-track)}.p-list-metric__progress-value{display:block;height:100%;border-radius:inherit;background:var(--p-list-metric-progress-fill)}.p-list-metric__progress--indeterminate{position:relative}.p-list-metric__progress--indeterminate .p-list-metric__progress-value{width:40%!important;animation:p-list-metric-progress 1.2s ease-in-out infinite}@keyframes p-list-metric-progress{0%{transform:translate(-100%)}to{transform:translate(250%)}}\n"] }]
|
|
8403
8593
|
}], propDecorators: { metric: [{
|
|
8404
8594
|
type: Input
|
|
8405
8595
|
}] } });
|
|
@@ -8462,6 +8652,7 @@ class ExecutiveAccountIdentityComponent {
|
|
|
8462
8652
|
<span class="account-identity">
|
|
8463
8653
|
<span class="account-identity__title-row">
|
|
8464
8654
|
<praxis-rich-content
|
|
8655
|
+
layout="inline"
|
|
8465
8656
|
rootClassName="account-identity__title-content"
|
|
8466
8657
|
[nodes]="titleNodes"
|
|
8467
8658
|
></praxis-rich-content>
|
|
@@ -8487,7 +8678,7 @@ class ExecutiveAccountIdentityComponent {
|
|
|
8487
8678
|
</span>
|
|
8488
8679
|
}
|
|
8489
8680
|
</span>
|
|
8490
|
-
`, isInline: true, styles: [":host{display:inline-flex;min-width:0}.account-identity{display:inline-flex;flex-direction:column;gap:4px;min-width:0}.account-identity__title-row{display:inline-flex;align-items:center;min-width:0}.account-identity__title-content{display:inline-flex;align-items:center;gap:8px;min-width:0}.account-identity__title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.05rem;font-weight:800;letter-spacing:-.016em;color:#183046;line-height:1.16}.account-identity__marker{color:#b89536;font-size:15px!important;width:15px!important;height:15px!important;flex-shrink:0;transform:translateY(1px)}.account-identity__subtitle-row{display:inline-flex;align-items:center;flex-wrap:
|
|
8681
|
+
`, isInline: true, styles: [":host{display:inline-flex;min-width:0;max-width:100%}.account-identity{display:inline-flex;flex-direction:column;gap:4px;min-width:0;max-width:100%}.account-identity__title-row{display:inline-flex;align-items:center;min-width:0;max-width:100%}.account-identity__title-content{display:inline-flex;align-items:center;gap:8px;min-width:0;max-width:100%}.account-identity__title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.05rem;font-weight:800;letter-spacing:-.016em;color:#183046;line-height:1.16}.account-identity__marker{color:#b89536;font-size:15px!important;width:15px!important;height:15px!important;flex-shrink:0;transform:translateY(1px)}.account-identity__subtitle-row{display:inline-flex;align-items:center;flex-wrap:nowrap;gap:6px;min-width:0;max-width:100%;overflow:hidden}.account-identity__meta{display:inline-flex;align-items:center;color:#7f90a4;white-space:nowrap;font-size:.76rem;line-height:1.18}.account-identity__separator{color:#a5b0bc;font-size:.74rem;line-height:1}\n"], dependencies: [{ kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }, { kind: "component", type: ExecutiveBadgeComponent, selector: "praxis-executive-badge", inputs: ["ariaLabel", "label", "variant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8491
8682
|
}
|
|
8492
8683
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ExecutiveAccountIdentityComponent, decorators: [{
|
|
8493
8684
|
type: Component,
|
|
@@ -8498,6 +8689,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8498
8689
|
<span class="account-identity">
|
|
8499
8690
|
<span class="account-identity__title-row">
|
|
8500
8691
|
<praxis-rich-content
|
|
8692
|
+
layout="inline"
|
|
8501
8693
|
rootClassName="account-identity__title-content"
|
|
8502
8694
|
[nodes]="titleNodes"
|
|
8503
8695
|
></praxis-rich-content>
|
|
@@ -8523,7 +8715,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8523
8715
|
</span>
|
|
8524
8716
|
}
|
|
8525
8717
|
</span>
|
|
8526
|
-
`, styles: [":host{display:inline-flex;min-width:0}.account-identity{display:inline-flex;flex-direction:column;gap:4px;min-width:0}.account-identity__title-row{display:inline-flex;align-items:center;min-width:0}.account-identity__title-content{display:inline-flex;align-items:center;gap:8px;min-width:0}.account-identity__title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.05rem;font-weight:800;letter-spacing:-.016em;color:#183046;line-height:1.16}.account-identity__marker{color:#b89536;font-size:15px!important;width:15px!important;height:15px!important;flex-shrink:0;transform:translateY(1px)}.account-identity__subtitle-row{display:inline-flex;align-items:center;flex-wrap:
|
|
8718
|
+
`, styles: [":host{display:inline-flex;min-width:0;max-width:100%}.account-identity{display:inline-flex;flex-direction:column;gap:4px;min-width:0;max-width:100%}.account-identity__title-row{display:inline-flex;align-items:center;min-width:0;max-width:100%}.account-identity__title-content{display:inline-flex;align-items:center;gap:8px;min-width:0;max-width:100%}.account-identity__title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.05rem;font-weight:800;letter-spacing:-.016em;color:#183046;line-height:1.16}.account-identity__marker{color:#b89536;font-size:15px!important;width:15px!important;height:15px!important;flex-shrink:0;transform:translateY(1px)}.account-identity__subtitle-row{display:inline-flex;align-items:center;flex-wrap:nowrap;gap:6px;min-width:0;max-width:100%;overflow:hidden}.account-identity__meta{display:inline-flex;align-items:center;color:#7f90a4;white-space:nowrap;font-size:.76rem;line-height:1.18}.account-identity__separator{color:#a5b0bc;font-size:.74rem;line-height:1}\n"] }]
|
|
8527
8719
|
}], propDecorators: { title: [{
|
|
8528
8720
|
type: Input
|
|
8529
8721
|
}], markerIcon: [{
|
|
@@ -8595,6 +8787,7 @@ class ExecutiveOwnerSummaryComponent {
|
|
|
8595
8787
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ExecutiveOwnerSummaryComponent, isStandalone: true, selector: "praxis-executive-owner-summary", inputs: { name: "name", icon: "icon" }, ngImport: i0, template: `
|
|
8596
8788
|
@if (displayIcon) {
|
|
8597
8789
|
<praxis-rich-content
|
|
8790
|
+
layout="inline"
|
|
8598
8791
|
class="owner-summary owner-summary--icon"
|
|
8599
8792
|
rootClassName="owner-summary__content"
|
|
8600
8793
|
[nodes]="ownerSummaryNodes"
|
|
@@ -8612,6 +8805,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8612
8805
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
8613
8806
|
@if (displayIcon) {
|
|
8614
8807
|
<praxis-rich-content
|
|
8808
|
+
layout="inline"
|
|
8615
8809
|
class="owner-summary owner-summary--icon"
|
|
8616
8810
|
rootClassName="owner-summary__content"
|
|
8617
8811
|
[nodes]="ownerSummaryNodes"
|
|
@@ -8738,7 +8932,7 @@ class PraxisListRuntimeComponentComponent {
|
|
|
8738
8932
|
}
|
|
8739
8933
|
}
|
|
8740
8934
|
</span>
|
|
8741
|
-
`, isInline: true, styles: [":host{display:inline-flex;min-width:0}.p-list-runtime-component{display:inline-flex;min-width:0}.p-list-runtime-component__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ExecutiveAccountIdentityComponent, selector: "praxis-executive-account-identity", inputs: ["title", "markerIcon", "segmentVariant", "segmentLabel", "accountType", "since"] }, { kind: "component", type: ExecutiveAlertSummaryComponent, selector: "praxis-executive-alert-summary", inputs: ["alerts"] }, { kind: "component", type: ExecutiveAlertsComponent, selector: "praxis-executive-alerts", inputs: ["alerts"] }, { kind: "component", type: ExecutiveBadgeComponent, selector: "praxis-executive-badge", inputs: ["ariaLabel", "label", "variant"] }, { kind: "component", type: ExecutiveOwnerComponent, selector: "praxis-executive-owner", inputs: ["name"] }, { kind: "component", type: ExecutiveOwnerSummaryComponent, selector: "praxis-executive-owner-summary", inputs: ["name", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8935
|
+
`, isInline: true, styles: [":host{display:inline-flex;min-width:0;max-width:100%}.p-list-runtime-component{display:inline-flex;min-width:0;max-width:100%}.p-list-runtime-component__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ExecutiveAccountIdentityComponent, selector: "praxis-executive-account-identity", inputs: ["title", "markerIcon", "segmentVariant", "segmentLabel", "accountType", "since"] }, { kind: "component", type: ExecutiveAlertSummaryComponent, selector: "praxis-executive-alert-summary", inputs: ["alerts"] }, { kind: "component", type: ExecutiveAlertsComponent, selector: "praxis-executive-alerts", inputs: ["alerts"] }, { kind: "component", type: ExecutiveBadgeComponent, selector: "praxis-executive-badge", inputs: ["ariaLabel", "label", "variant"] }, { kind: "component", type: ExecutiveOwnerComponent, selector: "praxis-executive-owner", inputs: ["name"] }, { kind: "component", type: ExecutiveOwnerSummaryComponent, selector: "praxis-executive-owner-summary", inputs: ["name", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8742
8936
|
}
|
|
8743
8937
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisListRuntimeComponentComponent, decorators: [{
|
|
8744
8938
|
type: Component,
|
|
@@ -8832,7 +9026,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
8832
9026
|
}
|
|
8833
9027
|
}
|
|
8834
9028
|
</span>
|
|
8835
|
-
`, styles: [":host{display:inline-flex;min-width:0}.p-list-runtime-component{display:inline-flex;min-width:0}.p-list-runtime-component__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}\n"] }]
|
|
9029
|
+
`, styles: [":host{display:inline-flex;min-width:0;max-width:100%}.p-list-runtime-component{display:inline-flex;min-width:0;max-width:100%}.p-list-runtime-component__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}\n"] }]
|
|
8836
9030
|
}], propDecorators: { component: [{
|
|
8837
9031
|
type: Input
|
|
8838
9032
|
}] } });
|
|
@@ -9099,7 +9293,10 @@ class PraxisListComposeComponent {
|
|
|
9099
9293
|
[style.cssText]="composeStyle(composeNode)"
|
|
9100
9294
|
>
|
|
9101
9295
|
@if (composeRichContentNodes(composeNode); as richNodes) {
|
|
9102
|
-
<praxis-rich-content
|
|
9296
|
+
<praxis-rich-content
|
|
9297
|
+
[layout]="composeNode?.direction === 'column' ? 'block' : 'inline'"
|
|
9298
|
+
[nodes]="richNodes"
|
|
9299
|
+
></praxis-rich-content>
|
|
9103
9300
|
} @else {
|
|
9104
9301
|
@for (node of composeNode?.items || []; track trackNode($index, node); let isLast = $last) {
|
|
9105
9302
|
<ng-container
|
|
@@ -9221,7 +9418,7 @@ class PraxisListComposeComponent {
|
|
|
9221
9418
|
}
|
|
9222
9419
|
}
|
|
9223
9420
|
</ng-template>
|
|
9224
|
-
`, isInline: true, styles: [":host{display:block;min-width:0}.p-list-compose{display:flex;min-width:0;width:100%}:host ::ng-deep .primary,:host ::ng-deep .secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%}:host ::ng-deep .primary{-webkit-line-clamp:1;font-weight:600;font-size:var(--p-list-primary-size, .92rem);line-height:1.3;color:var(--p-list-foreground)}:host ::ng-deep .secondary{-webkit-line-clamp:1;font-size:var(--p-list-secondary-size, .78rem);line-height:1.3;color:var(--p-list-foreground-muted)}.p-list-compose--direction-row{flex-direction:row}.p-list-compose--direction-column{flex-direction:column}.p-list-compose--align-start{align-items:flex-start}.p-list-compose--align-center{align-items:center}.p-list-compose--align-end{align-items:flex-end}.p-list-compose--wrap{flex-wrap:wrap}.p-list-compose--nowrap{flex-wrap:nowrap}.p-list-compose__separator{color:var(--p-list-foreground-muted);white-space:pre-wrap}.p-list-compose__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}:host ::ng-deep .mat-mdc-standard-chip:not(.mdc-evolution-chip--disabled){background-color:var( --p-list-chip-background, color-mix(in srgb, var(--p-list-surface-alt) 85%, transparent) )!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, var(--p-list-border))!important}:host ::ng-deep .chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }, { kind: "component", type: PraxisListMetricComponent, selector: "praxis-list-metric", inputs: ["metric"] }, { kind: "component", type: PraxisListRuntimeComponentComponent, selector: "praxis-list-runtime-component", inputs: ["component"] }] });
|
|
9421
|
+
`, isInline: true, styles: [":host{display:block;min-width:0;max-width:100%}.p-list-compose{display:flex;min-width:0;max-width:100%;width:100%}.p-list-compose>praxis-rich-content{min-width:0;max-width:100%;width:100%}:host ::ng-deep .primary,:host ::ng-deep .secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%}:host ::ng-deep .primary .prx-rich-text,:host ::ng-deep .secondary .prx-rich-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%}:host ::ng-deep .primary{-webkit-line-clamp:1;font-weight:600;font-size:var(--p-list-primary-size, .92rem);line-height:1.3;color:var(--p-list-foreground)}:host ::ng-deep .secondary{-webkit-line-clamp:1;font-size:var(--p-list-secondary-size, .78rem);line-height:1.3;color:var(--p-list-foreground-muted)}.p-list-compose--direction-row{flex-direction:row}.p-list-compose--direction-column{flex-direction:column}.p-list-compose--align-start{align-items:flex-start}.p-list-compose--align-center{align-items:center}.p-list-compose--align-end{align-items:flex-end}.p-list-compose--wrap{flex-wrap:wrap}.p-list-compose--nowrap{flex-wrap:nowrap}.p-list-compose__separator{color:var(--p-list-foreground-muted);white-space:pre-wrap}.p-list-compose__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}:host ::ng-deep .mat-mdc-standard-chip:not(.mdc-evolution-chip--disabled){background-color:var( --p-list-chip-background, color-mix(in srgb, var(--p-list-surface-alt) 85%, transparent) )!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, var(--p-list-border))!important}:host ::ng-deep .chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }, { kind: "component", type: PraxisListMetricComponent, selector: "praxis-list-metric", inputs: ["metric"] }, { kind: "component", type: PraxisListRuntimeComponentComponent, selector: "praxis-list-runtime-component", inputs: ["component"] }] });
|
|
9225
9422
|
}
|
|
9226
9423
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisListComposeComponent, decorators: [{
|
|
9227
9424
|
type: Component,
|
|
@@ -9245,7 +9442,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9245
9442
|
[style.cssText]="composeStyle(composeNode)"
|
|
9246
9443
|
>
|
|
9247
9444
|
@if (composeRichContentNodes(composeNode); as richNodes) {
|
|
9248
|
-
<praxis-rich-content
|
|
9445
|
+
<praxis-rich-content
|
|
9446
|
+
[layout]="composeNode?.direction === 'column' ? 'block' : 'inline'"
|
|
9447
|
+
[nodes]="richNodes"
|
|
9448
|
+
></praxis-rich-content>
|
|
9249
9449
|
} @else {
|
|
9250
9450
|
@for (node of composeNode?.items || []; track trackNode($index, node); let isLast = $last) {
|
|
9251
9451
|
<ng-container
|
|
@@ -9367,7 +9567,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9367
9567
|
}
|
|
9368
9568
|
}
|
|
9369
9569
|
</ng-template>
|
|
9370
|
-
`, styles: [":host{display:block;min-width:0}.p-list-compose{display:flex;min-width:0;width:100%}:host ::ng-deep .primary,:host ::ng-deep .secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%}:host ::ng-deep .primary{-webkit-line-clamp:1;font-weight:600;font-size:var(--p-list-primary-size, .92rem);line-height:1.3;color:var(--p-list-foreground)}:host ::ng-deep .secondary{-webkit-line-clamp:1;font-size:var(--p-list-secondary-size, .78rem);line-height:1.3;color:var(--p-list-foreground-muted)}.p-list-compose--direction-row{flex-direction:row}.p-list-compose--direction-column{flex-direction:column}.p-list-compose--align-start{align-items:flex-start}.p-list-compose--align-center{align-items:center}.p-list-compose--align-end{align-items:flex-end}.p-list-compose--wrap{flex-wrap:wrap}.p-list-compose--nowrap{flex-wrap:nowrap}.p-list-compose__separator{color:var(--p-list-foreground-muted);white-space:pre-wrap}.p-list-compose__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}:host ::ng-deep .mat-mdc-standard-chip:not(.mdc-evolution-chip--disabled){background-color:var( --p-list-chip-background, color-mix(in srgb, var(--p-list-surface-alt) 85%, transparent) )!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, var(--p-list-border))!important}:host ::ng-deep .chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important}\n"] }]
|
|
9570
|
+
`, styles: [":host{display:block;min-width:0;max-width:100%}.p-list-compose{display:flex;min-width:0;max-width:100%;width:100%}.p-list-compose>praxis-rich-content{min-width:0;max-width:100%;width:100%}:host ::ng-deep .primary,:host ::ng-deep .secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%}:host ::ng-deep .primary .prx-rich-text,:host ::ng-deep .secondary .prx-rich-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%}:host ::ng-deep .primary{-webkit-line-clamp:1;font-weight:600;font-size:var(--p-list-primary-size, .92rem);line-height:1.3;color:var(--p-list-foreground)}:host ::ng-deep .secondary{-webkit-line-clamp:1;font-size:var(--p-list-secondary-size, .78rem);line-height:1.3;color:var(--p-list-foreground-muted)}.p-list-compose--direction-row{flex-direction:row}.p-list-compose--direction-column{flex-direction:column}.p-list-compose--align-start{align-items:flex-start}.p-list-compose--align-center{align-items:center}.p-list-compose--align-end{align-items:flex-end}.p-list-compose--wrap{flex-wrap:wrap}.p-list-compose--nowrap{flex-wrap:nowrap}.p-list-compose__separator{color:var(--p-list-foreground-muted);white-space:pre-wrap}.p-list-compose__unsupported{display:inline-flex;align-items:center;justify-content:center;width:.75rem;height:.75rem;min-width:.75rem;border:1px dashed var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;color:transparent;font-size:0;line-height:0}:host ::ng-deep .mat-mdc-standard-chip:not(.mdc-evolution-chip--disabled){background-color:var( --p-list-chip-background, color-mix(in srgb, var(--p-list-surface-alt) 85%, transparent) )!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, var(--p-list-border))!important}:host ::ng-deep .chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;color:var(--p-list-chip-color, var(--p-list-foreground))!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important}\n"] }]
|
|
9371
9571
|
}], propDecorators: { compose: [{
|
|
9372
9572
|
type: Input
|
|
9373
9573
|
}] } });
|
|
@@ -9439,6 +9639,8 @@ class PraxisList {
|
|
|
9439
9639
|
lastQuery = {};
|
|
9440
9640
|
lastRuntimeQueryContextSignature = '';
|
|
9441
9641
|
search$ = new Subject();
|
|
9642
|
+
activeSearchTerm = '';
|
|
9643
|
+
searchInputRef;
|
|
9442
9644
|
get layoutLines() {
|
|
9443
9645
|
return this.config?.layout?.lines ?? 2;
|
|
9444
9646
|
}
|
|
@@ -9631,6 +9833,17 @@ class PraxisList {
|
|
|
9631
9833
|
return;
|
|
9632
9834
|
if (this.configPersistenceStrategy === 'input-first')
|
|
9633
9835
|
return;
|
|
9836
|
+
const currentPath = String(this.config?.dataSource?.resourcePath ?? '')
|
|
9837
|
+
.trim()
|
|
9838
|
+
.replace(/^\/+|\/+$/g, '')
|
|
9839
|
+
.toLowerCase();
|
|
9840
|
+
const savedPath = String(saved?.dataSource?.resourcePath ?? '')
|
|
9841
|
+
.trim()
|
|
9842
|
+
.replace(/^\/+|\/+$/g, '')
|
|
9843
|
+
.toLowerCase();
|
|
9844
|
+
if (currentPath.length > 0 && savedPath.length > 0 && currentPath !== savedPath) {
|
|
9845
|
+
return;
|
|
9846
|
+
}
|
|
9634
9847
|
const currentId = this.config?.id;
|
|
9635
9848
|
const persisted = currentId
|
|
9636
9849
|
? { ...saved, id: currentId }
|
|
@@ -9671,9 +9884,17 @@ class PraxisList {
|
|
|
9671
9884
|
const field = this.config?.ui?.searchField;
|
|
9672
9885
|
if (!field)
|
|
9673
9886
|
return;
|
|
9674
|
-
const
|
|
9887
|
+
const normalizedTerm = String(term ?? '').trim();
|
|
9888
|
+
const q = { ...(this.lastQuery || {}) };
|
|
9889
|
+
if (normalizedTerm) {
|
|
9890
|
+
q[field] = term;
|
|
9891
|
+
}
|
|
9892
|
+
else {
|
|
9893
|
+
delete q[field];
|
|
9894
|
+
}
|
|
9675
9895
|
this.lastQuery = q;
|
|
9676
9896
|
this.data.setQuery(q);
|
|
9897
|
+
this.cdr.markForCheck();
|
|
9677
9898
|
});
|
|
9678
9899
|
}
|
|
9679
9900
|
async persistConfig(key, config) {
|
|
@@ -10665,6 +10886,81 @@ class PraxisList {
|
|
|
10665
10886
|
const label = this.accessibleItemLabel(item);
|
|
10666
10887
|
return `${label} - ${this.t('itemDetails', 'Detalhes do item').toLowerCase()}`;
|
|
10667
10888
|
}
|
|
10889
|
+
hasCustomEmptyStateTemplate() {
|
|
10890
|
+
return Boolean(this.evalSlot('emptyState', {}));
|
|
10891
|
+
}
|
|
10892
|
+
hasActiveEmptyStateFilters() {
|
|
10893
|
+
if (this.isResourceConnectionMissing())
|
|
10894
|
+
return false;
|
|
10895
|
+
if (this.activeSearchTerm.trim().length > 0)
|
|
10896
|
+
return true;
|
|
10897
|
+
const normalized = normalizePraxisDataQueryContext(this.runtimeQueryContext);
|
|
10898
|
+
const contextFilters = normalized?.filters || {};
|
|
10899
|
+
return Object.values(contextFilters).some((val) => val !== undefined &&
|
|
10900
|
+
val !== null &&
|
|
10901
|
+
String(val).trim().length > 0);
|
|
10902
|
+
}
|
|
10903
|
+
emptyStateIcon() {
|
|
10904
|
+
if (this.isResourceConnectionMissing()) {
|
|
10905
|
+
return 'link';
|
|
10906
|
+
}
|
|
10907
|
+
if (this.hasActiveEmptyStateFilters()) {
|
|
10908
|
+
return 'search_off';
|
|
10909
|
+
}
|
|
10910
|
+
return 'inbox';
|
|
10911
|
+
}
|
|
10912
|
+
emptyStateTitle() {
|
|
10913
|
+
if (this.isResourceConnectionMissing()) {
|
|
10914
|
+
return this.t('emptyStateConnectResourceTitle', 'Escolha o recurso da lista');
|
|
10915
|
+
}
|
|
10916
|
+
if (this.hasActiveEmptyStateFilters()) {
|
|
10917
|
+
return this.t('emptyStateFilteredTitle', 'Nenhum resultado encontrado');
|
|
10918
|
+
}
|
|
10919
|
+
return this.emptyStateLabel();
|
|
10920
|
+
}
|
|
10921
|
+
emptyStateDescription() {
|
|
10922
|
+
if (this.isResourceConnectionMissing()) {
|
|
10923
|
+
return this.emptyStateLabel();
|
|
10924
|
+
}
|
|
10925
|
+
if (this.hasActiveEmptyStateFilters()) {
|
|
10926
|
+
return this.t('emptyStateFilteredDescription', 'Revise os filtros ou ajuste o termo de busca.');
|
|
10927
|
+
}
|
|
10928
|
+
return this.t('emptyStateDescription', 'Não há itens para exibir neste momento.');
|
|
10929
|
+
}
|
|
10930
|
+
emptyStatePrimaryAction() {
|
|
10931
|
+
if (!this.isResourceConnectionMissing() || !this.enableCustomization) {
|
|
10932
|
+
return undefined;
|
|
10933
|
+
}
|
|
10934
|
+
return {
|
|
10935
|
+
label: this.t('emptyStateConnectResourceAction', 'Selecionar recurso'),
|
|
10936
|
+
icon: 'bolt',
|
|
10937
|
+
action: () => this.openQuickConnect(),
|
|
10938
|
+
};
|
|
10939
|
+
}
|
|
10940
|
+
emptyStateSecondaryActions() {
|
|
10941
|
+
if (this.isResourceConnectionMissing()) {
|
|
10942
|
+
if (!this.enableCustomization) {
|
|
10943
|
+
return [];
|
|
10944
|
+
}
|
|
10945
|
+
return [
|
|
10946
|
+
{
|
|
10947
|
+
label: this.t('emptyStateConfigureAction', 'Configurar lista'),
|
|
10948
|
+
icon: 'tune',
|
|
10949
|
+
action: () => this.openConfigEditor(),
|
|
10950
|
+
},
|
|
10951
|
+
];
|
|
10952
|
+
}
|
|
10953
|
+
if (this.activeSearchTerm.trim().length > 0) {
|
|
10954
|
+
return [
|
|
10955
|
+
{
|
|
10956
|
+
label: this.t('emptyStateClearSearchAction', 'Limpar busca'),
|
|
10957
|
+
icon: 'filter_alt_off',
|
|
10958
|
+
action: () => this.clearSearch(),
|
|
10959
|
+
},
|
|
10960
|
+
];
|
|
10961
|
+
}
|
|
10962
|
+
return [];
|
|
10963
|
+
}
|
|
10668
10964
|
emptyStateLabel() {
|
|
10669
10965
|
if (this.isResourceConnectionMissing()) {
|
|
10670
10966
|
return this.t('emptyStateConnectResource', 'Conecte a lista a um recurso para carregar os itens.');
|
|
@@ -11249,6 +11545,58 @@ class PraxisList {
|
|
|
11249
11545
|
return value;
|
|
11250
11546
|
}
|
|
11251
11547
|
}
|
|
11548
|
+
openQuickConnect() {
|
|
11549
|
+
if (!this.enableCustomization)
|
|
11550
|
+
return;
|
|
11551
|
+
const key = this.storageKey();
|
|
11552
|
+
const currentResourcePath = String(this.config?.dataSource?.resourcePath || '').trim();
|
|
11553
|
+
const ref = this.settings.open({
|
|
11554
|
+
id: `praxis-list:quick-connect:${key || this.listId || 'default'}`,
|
|
11555
|
+
owner: this.destroyRef,
|
|
11556
|
+
title: this.t('emptyStateConnectResourceTitle', 'Escolha o recurso da lista'),
|
|
11557
|
+
content: {
|
|
11558
|
+
component: ResourceQuickConnectComponent,
|
|
11559
|
+
inputs: {
|
|
11560
|
+
resourcePath: currentResourcePath || undefined,
|
|
11561
|
+
intent: 'collection',
|
|
11562
|
+
},
|
|
11563
|
+
},
|
|
11564
|
+
});
|
|
11565
|
+
const applyResourceSelection = (val, trigger) => {
|
|
11566
|
+
const nextResourcePath = String(val?.resourcePath || '').trim();
|
|
11567
|
+
if (!nextResourcePath)
|
|
11568
|
+
return;
|
|
11569
|
+
const resourceChanged = Boolean(currentResourcePath) &&
|
|
11570
|
+
currentResourcePath !== nextResourcePath;
|
|
11571
|
+
if (resourceChanged) {
|
|
11572
|
+
this.activeSearchTerm = '';
|
|
11573
|
+
if (this.searchInputRef?.nativeElement) {
|
|
11574
|
+
this.searchInputRef.nativeElement.value = '';
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
const { data: _ignoredLocalData, query: existingQuery, sort: existingSort, ...restDataSource } = this.config?.dataSource || {};
|
|
11578
|
+
const nextConfig = {
|
|
11579
|
+
...(this.config || {}),
|
|
11580
|
+
dataSource: {
|
|
11581
|
+
...restDataSource,
|
|
11582
|
+
...(resourceChanged
|
|
11583
|
+
? {}
|
|
11584
|
+
: {
|
|
11585
|
+
...(existingQuery ? { query: existingQuery } : {}),
|
|
11586
|
+
...(existingSort ? { sort: existingSort } : {}),
|
|
11587
|
+
}),
|
|
11588
|
+
resourcePath: nextResourcePath,
|
|
11589
|
+
},
|
|
11590
|
+
};
|
|
11591
|
+
this.applyAuthoringPayload(nextConfig, trigger);
|
|
11592
|
+
};
|
|
11593
|
+
ref.applied$?.pipe(takeUntil(this.destroy$)).subscribe((val) => {
|
|
11594
|
+
applyResourceSelection(val, 'settings-applied');
|
|
11595
|
+
});
|
|
11596
|
+
ref.saved$?.pipe(takeUntil(this.destroy$)).subscribe((val) => {
|
|
11597
|
+
applyResourceSelection(val, 'settings-saved');
|
|
11598
|
+
});
|
|
11599
|
+
}
|
|
11252
11600
|
openConfigEditor() {
|
|
11253
11601
|
void this.openConfigEditorPanel().catch((error) => {
|
|
11254
11602
|
this.logger.error('[PraxisList] Error opening list settings.', this.buildLogOptions({ error }));
|
|
@@ -11623,7 +11971,24 @@ class PraxisList {
|
|
|
11623
11971
|
?.focus({ preventScroll: true });
|
|
11624
11972
|
}
|
|
11625
11973
|
onSearchInput(val) {
|
|
11626
|
-
this.
|
|
11974
|
+
this.activeSearchTerm = val || '';
|
|
11975
|
+
this.search$.next(this.activeSearchTerm);
|
|
11976
|
+
this.cdr.markForCheck();
|
|
11977
|
+
}
|
|
11978
|
+
clearSearch() {
|
|
11979
|
+
this.activeSearchTerm = '';
|
|
11980
|
+
if (this.searchInputRef?.nativeElement) {
|
|
11981
|
+
this.searchInputRef.nativeElement.value = '';
|
|
11982
|
+
}
|
|
11983
|
+
const field = this.config?.ui?.searchField;
|
|
11984
|
+
if (field && this.lastQuery && field in this.lastQuery) {
|
|
11985
|
+
const q = { ...this.lastQuery };
|
|
11986
|
+
delete q[field];
|
|
11987
|
+
this.lastQuery = q;
|
|
11988
|
+
this.data.setQuery(q);
|
|
11989
|
+
}
|
|
11990
|
+
this.search$.next('');
|
|
11991
|
+
this.cdr.markForCheck();
|
|
11627
11992
|
}
|
|
11628
11993
|
isRemoteDataMode() {
|
|
11629
11994
|
const dataSource = this.config?.dataSource;
|
|
@@ -11739,8 +12104,28 @@ class PraxisList {
|
|
|
11739
12104
|
if (plan.diagnostics.some((item) => item.level === 'error')) {
|
|
11740
12105
|
return;
|
|
11741
12106
|
}
|
|
12107
|
+
const prevResourcePath = String(this.appliedRuntimeConfig?.dataSource?.resourcePath || '')
|
|
12108
|
+
.trim()
|
|
12109
|
+
.replace(/^\/+|\/+$/g, '')
|
|
12110
|
+
.replace(/^api\//i, '')
|
|
12111
|
+
.toLowerCase();
|
|
12112
|
+
const nextConfig = normalizeListConfig(plan.canonicalConfig);
|
|
12113
|
+
const nextResourcePath = String(nextConfig?.dataSource?.resourcePath || '')
|
|
12114
|
+
.trim()
|
|
12115
|
+
.replace(/^\/+|\/+$/g, '')
|
|
12116
|
+
.replace(/^api\//i, '')
|
|
12117
|
+
.toLowerCase();
|
|
12118
|
+
if (prevResourcePath.length > 0 &&
|
|
12119
|
+
nextResourcePath.length > 0 &&
|
|
12120
|
+
prevResourcePath !== nextResourcePath) {
|
|
12121
|
+
this.activeSearchTerm = '';
|
|
12122
|
+
if (this.searchInputRef?.nativeElement) {
|
|
12123
|
+
this.searchInputRef.nativeElement.value = '';
|
|
12124
|
+
}
|
|
12125
|
+
this.expandedItemKeys = new Set();
|
|
12126
|
+
}
|
|
11742
12127
|
this.initializeDataStreams();
|
|
11743
|
-
this.config =
|
|
12128
|
+
this.config = nextConfig;
|
|
11744
12129
|
this.appliedRuntimeConfig = this.config;
|
|
11745
12130
|
this.syncPaginatorIntl();
|
|
11746
12131
|
this.syncExpansionState();
|
|
@@ -11765,9 +12150,6 @@ class PraxisList {
|
|
|
11765
12150
|
});
|
|
11766
12151
|
}
|
|
11767
12152
|
}
|
|
11768
|
-
if (plan.runtime?.schemaInference) {
|
|
11769
|
-
this.executeSchemaInferenceForPlan(plan.runtime.schemaInference, plan.persistence?.saveConfig === true);
|
|
11770
|
-
}
|
|
11771
12153
|
if (plan.runtime?.markForCheck) {
|
|
11772
12154
|
this.cdr.markForCheck();
|
|
11773
12155
|
}
|
|
@@ -11778,6 +12160,11 @@ class PraxisList {
|
|
|
11778
12160
|
inputPatch: { config: normalizeListConfig(plan.canonicalConfig) },
|
|
11779
12161
|
});
|
|
11780
12162
|
}
|
|
12163
|
+
if (plan.runtime?.schemaInference) {
|
|
12164
|
+
this.executeSchemaInferenceForPlan(plan.runtime.schemaInference, plan.persistence?.saveConfig === true, trigger === 'settings-applied' ||
|
|
12165
|
+
trigger === 'settings-saved' ||
|
|
12166
|
+
trigger === 'adapter');
|
|
12167
|
+
}
|
|
11781
12168
|
}
|
|
11782
12169
|
storageKey() {
|
|
11783
12170
|
if (this.configPersistenceStrategy === 'volatile') {
|
|
@@ -11804,33 +12191,59 @@ class PraxisList {
|
|
|
11804
12191
|
crud = inject(GenericCrudService, {
|
|
11805
12192
|
optional: true,
|
|
11806
12193
|
});
|
|
11807
|
-
|
|
12194
|
+
resourceDiscovery = inject(ResourceDiscoveryService, {
|
|
12195
|
+
optional: true,
|
|
12196
|
+
});
|
|
12197
|
+
executeSchemaInferenceForPlan(inferencePlan, saveAfterInference = false, publishAuthoringPatch = false) {
|
|
11808
12198
|
const resourcePath = inferencePlan.resourcePath;
|
|
11809
|
-
|
|
12199
|
+
const canDiscover = typeof this.resourceDiscovery?.getResourceSchemaFields === 'function' &&
|
|
12200
|
+
(typeof this.resourceDiscovery.canResolveSchemas !== 'function' ||
|
|
12201
|
+
this.resourceDiscovery.canResolveSchemas());
|
|
12202
|
+
if (!resourcePath || (!this.crud && !canDiscover))
|
|
11810
12203
|
return;
|
|
11811
|
-
|
|
12204
|
+
const inferenceTrigger = saveAfterInference
|
|
12205
|
+
? 'settings-saved'
|
|
12206
|
+
: publishAuthoringPatch
|
|
12207
|
+
? 'settings-applied'
|
|
12208
|
+
: 'schema-inference';
|
|
12209
|
+
const cachedNames = this.schemaFieldsByPath.get(resourcePath);
|
|
12210
|
+
if (this.inferredForPath.has(resourcePath) && cachedNames?.length) {
|
|
12211
|
+
const inferredDocument = inferListAuthoringDocument(inferencePlan.sourceDocument, { schemaFieldNames: cachedNames });
|
|
12212
|
+
if (JSON.stringify(inferredDocument.config) !==
|
|
12213
|
+
JSON.stringify(inferencePlan.sourceDocument.config)) {
|
|
12214
|
+
this.applyAuthoringPayload(inferredDocument, inferenceTrigger);
|
|
12215
|
+
}
|
|
11812
12216
|
return;
|
|
12217
|
+
}
|
|
11813
12218
|
if (this.schemaInferenceInFlight.has(resourcePath))
|
|
11814
12219
|
return;
|
|
11815
12220
|
this.schemaInferenceInFlight.add(resourcePath);
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
.
|
|
12221
|
+
const applyInferredFields = (fields) => {
|
|
12222
|
+
const names = (fields || [])
|
|
12223
|
+
.map((field) => field?.name || field?.field || field?.key)
|
|
12224
|
+
.filter(Boolean);
|
|
12225
|
+
if (!names.length)
|
|
12226
|
+
return false;
|
|
12227
|
+
this.inferredForPath.add(resourcePath);
|
|
12228
|
+
this.schemaFieldsByPath.set(resourcePath, names);
|
|
12229
|
+
const inferredDocument = inferListAuthoringDocument(inferencePlan.sourceDocument, {
|
|
12230
|
+
schemaFieldNames: names,
|
|
12231
|
+
});
|
|
12232
|
+
this.applyAuthoringPayload(inferredDocument, inferenceTrigger);
|
|
12233
|
+
return true;
|
|
12234
|
+
};
|
|
12235
|
+
const tryDiscoveryFallback = () => {
|
|
12236
|
+
if (!canDiscover || !this.resourceDiscovery) {
|
|
12237
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12238
|
+
this.schemaFieldsByPath.delete(resourcePath);
|
|
12239
|
+
return;
|
|
12240
|
+
}
|
|
12241
|
+
this.resourceDiscovery
|
|
12242
|
+
.getResourceSchemaFields(resourcePath)
|
|
11820
12243
|
.pipe(take(1))
|
|
11821
12244
|
.subscribe({
|
|
11822
12245
|
next: (fields) => {
|
|
11823
|
-
|
|
11824
|
-
.map((field) => field?.name || field?.field || field?.key)
|
|
11825
|
-
.filter(Boolean);
|
|
11826
|
-
if (!names.length)
|
|
11827
|
-
return;
|
|
11828
|
-
this.inferredForPath.add(resourcePath);
|
|
11829
|
-
this.schemaFieldsByPath.set(resourcePath, names);
|
|
11830
|
-
const inferredDocument = inferListAuthoringDocument(inferencePlan.sourceDocument, {
|
|
11831
|
-
schemaFieldNames: names,
|
|
11832
|
-
});
|
|
11833
|
-
this.applyAuthoringPayload(inferredDocument, saveAfterInference ? 'settings-saved' : 'schema-inference');
|
|
12246
|
+
applyInferredFields(fields);
|
|
11834
12247
|
},
|
|
11835
12248
|
error: () => {
|
|
11836
12249
|
this.schemaInferenceInFlight.delete(resourcePath);
|
|
@@ -11840,10 +12253,78 @@ class PraxisList {
|
|
|
11840
12253
|
this.schemaInferenceInFlight.delete(resourcePath);
|
|
11841
12254
|
},
|
|
11842
12255
|
});
|
|
12256
|
+
};
|
|
12257
|
+
const tryCrudFallback = () => {
|
|
12258
|
+
if (!this.crud) {
|
|
12259
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12260
|
+
this.schemaFieldsByPath.delete(resourcePath);
|
|
12261
|
+
return;
|
|
12262
|
+
}
|
|
12263
|
+
try {
|
|
12264
|
+
this.crud.configure(resourcePath);
|
|
12265
|
+
this.crud
|
|
12266
|
+
.getSchema()
|
|
12267
|
+
.pipe(take(1))
|
|
12268
|
+
.subscribe({
|
|
12269
|
+
next: (crudFields) => applyInferredFields(crudFields),
|
|
12270
|
+
error: () => {
|
|
12271
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12272
|
+
this.schemaFieldsByPath.delete(resourcePath);
|
|
12273
|
+
},
|
|
12274
|
+
complete: () => {
|
|
12275
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12276
|
+
},
|
|
12277
|
+
});
|
|
12278
|
+
}
|
|
12279
|
+
catch {
|
|
12280
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12281
|
+
this.schemaFieldsByPath.delete(resourcePath);
|
|
12282
|
+
}
|
|
12283
|
+
};
|
|
12284
|
+
const isCatalogResourceKey = !resourcePath.includes('/') && resourcePath.includes('.');
|
|
12285
|
+
if (isCatalogResourceKey && canDiscover && this.resourceDiscovery) {
|
|
12286
|
+
this.resourceDiscovery
|
|
12287
|
+
.getResourceSchemaFields(resourcePath)
|
|
12288
|
+
.pipe(take(1))
|
|
12289
|
+
.subscribe({
|
|
12290
|
+
next: (fields) => {
|
|
12291
|
+
if (!applyInferredFields(fields)) {
|
|
12292
|
+
tryCrudFallback();
|
|
12293
|
+
}
|
|
12294
|
+
else {
|
|
12295
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12296
|
+
}
|
|
12297
|
+
},
|
|
12298
|
+
error: () => {
|
|
12299
|
+
tryCrudFallback();
|
|
12300
|
+
},
|
|
12301
|
+
});
|
|
12302
|
+
return;
|
|
12303
|
+
}
|
|
12304
|
+
try {
|
|
12305
|
+
if (!this.crud) {
|
|
12306
|
+
tryDiscoveryFallback();
|
|
12307
|
+
return;
|
|
12308
|
+
}
|
|
12309
|
+
this.crud.configure(resourcePath);
|
|
12310
|
+
this.crud
|
|
12311
|
+
.getSchema()
|
|
12312
|
+
.pipe(take(1))
|
|
12313
|
+
.subscribe({
|
|
12314
|
+
next: (fields) => {
|
|
12315
|
+
if (!applyInferredFields(fields)) {
|
|
12316
|
+
tryDiscoveryFallback();
|
|
12317
|
+
return;
|
|
12318
|
+
}
|
|
12319
|
+
this.schemaInferenceInFlight.delete(resourcePath);
|
|
12320
|
+
},
|
|
12321
|
+
error: () => {
|
|
12322
|
+
tryDiscoveryFallback();
|
|
12323
|
+
},
|
|
12324
|
+
});
|
|
11843
12325
|
}
|
|
11844
12326
|
catch {
|
|
11845
|
-
|
|
11846
|
-
this.schemaFieldsByPath.delete(resourcePath);
|
|
12327
|
+
tryDiscoveryFallback();
|
|
11847
12328
|
}
|
|
11848
12329
|
}
|
|
11849
12330
|
evalSlot(slot, item) {
|
|
@@ -12185,6 +12666,9 @@ class PraxisList {
|
|
|
12185
12666
|
}
|
|
12186
12667
|
expansionSectionHasContent(item, section, index) {
|
|
12187
12668
|
if (section?.type === 'rich-content') {
|
|
12669
|
+
if (section?.itemsExpr) {
|
|
12670
|
+
return this.expansionSectionItems(item, section, index).length > 0;
|
|
12671
|
+
}
|
|
12188
12672
|
const document = this.expansionRichContentDocument(item, section, index);
|
|
12189
12673
|
return Array.isArray(document?.nodes) && document.nodes.length > 0;
|
|
12190
12674
|
}
|
|
@@ -12870,7 +13354,7 @@ class PraxisList {
|
|
|
12870
13354
|
ListDataService,
|
|
12871
13355
|
MatPaginatorIntl,
|
|
12872
13356
|
providePraxisListI18n(),
|
|
12873
|
-
], usesOnChanges: true, ngImport: i0, template: "<div class=\"list-loading-status\" role=\"status\">\n @if (loading$ | async) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\" aria-hidden=\"true\"></mat-progress-spinner>\n <span>{{ t('loading', 'Carregando itens\u2026') }}</span>\n }\n</div>\n<div\n class=\"praxis-list-root\"\n tabindex=\"-1\"\n [attr.aria-busy]=\"(loading$ | async) ? 'true' : 'false'\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.data-item-appearance]=\"config?.layout?.itemAppearance || null\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (enableCustomization) {\n <div class=\"list-assistant\">\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openConfigEditor()\"\n [matTooltip]=\"configEditorLabel()\"\n [attr.aria-label]=\"configEditorLabel()\"\n data-testid=\"praxis-list-open-config-editor\"\n >\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openAiAssistant()\"\n matTooltip=\"Copiloto semantico Praxis\"\n aria-label=\"Abrir copiloto semantico Praxis da lista\"\n data-testid=\"praxis-list-ai-assistant-trigger\"\n >\n <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"\n aiAssistantViewState.state === 'processing' ||\n aiAssistantViewState.state === 'applying'\n \"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-list-ai-assistant\"\n panelTestId=\"praxis-list-ai-assistant-panel\"\n submitTestId=\"praxis-list-ai-assistant-submit\"\n applyTestId=\"praxis-list-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n\n @if (\n config.export?.enabled ||\n (isRemoteDataMode() &&\n (config.ui?.showSort ||\n (config.ui?.showSearch && config.ui?.searchField)))\n ) {\n <div\n class=\"list-collection-toolbar\"\n role=\"group\"\n [attr.aria-label]=\"t('toolbar.label', 'Controles da lista')\"\n >\n @if (\n isRemoteDataMode() && config.ui?.showSearch && config.ui?.searchField\n ) {\n <mat-form-field\n class=\"list-toolbar-search\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{\n config.ui?.searchPlaceholder || t(\"toolbar.search\", \"Buscar\")\n }}</mat-label>\n <mat-icon matPrefix [praxisIcon]=\"'search'\"></mat-icon>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n\n <div class=\"list-toolbar-commands\">\n @if (isRemoteDataMode() && config.ui?.showSort) {\n <mat-form-field\n class=\"list-toolbar-sort\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{ t(\"toolbar.sort\", \"Ordenar por\") }}</mat-label>\n @let activeSort = activeSortValue((page$ | async)?.sort);\n <mat-select\n [value]=\"activeSort\"\n (selectionChange)=\"onSortChange($event.value)\"\n >\n @if (activeSort && !hasSortOption(activeSort)) {\n <mat-option [value]=\"activeSort\">{{ activeSort }}</mat-option>\n }\n @for (op of config.ui?.sortOptions || []; track $index) {\n <mat-option [value]=\"sortOptionValue(op)\">{{\n sortOptionLabel(op)\n }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (config.export?.enabled) {\n <button\n mat-stroked-button\n type=\"button\"\n [matMenuTriggerFor]=\"listExportMenu\"\n [attr.aria-label]=\"t('export.button', 'Exportar')\"\n [disabled]=\"exportBusy\"\n [attr.aria-busy]=\"exportBusy\"\n >\n <mat-icon [praxisIcon]=\"'download'\"></mat-icon>\n {{ t(\"export.button\", \"Exportar\") }}\n </button>\n <span class=\"cdk-visually-hidden\" aria-live=\"polite\">\n {{ exportStatusMessage }}\n </span>\n <mat-menu #listExportMenu=\"matMenu\">\n @for (format of listExportFormats(); track format) {\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"onExportAction(format)\"\n >\n <mat-icon [praxisIcon]=\"exportIcon(format)\"></mat-icon>\n {{ format.toUpperCase() }}\n </button>\n }\n </mat-menu>\n }\n </div>\n </div>\n }\n\n <!-- Skeleton while loading -->\n @if (loading$ | async) {\n @if (hasSkeleton()) {\n @if (isListVariant()) {\n <mat-list>\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <mat-list-item>\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else {\n <div class=\"cards-grid\">\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (error$ | async; as remoteError) {\n <div class=\"list-remote-error\" role=\"alert\">\n <mat-icon [praxisIcon]=\"'error_outline'\"></mat-icon>\n <div class=\"list-remote-error__copy\">\n <strong>{{\n t(\"remoteError.title\", \"N\u00E3o foi poss\u00EDvel carregar a lista\")\n }}</strong>\n <span>\n {{\n remoteError.filtered\n ? t(\n \"remoteError.filteredDescription\",\n \"Os filtros permanecem aplicados. Nenhum dado sem filtro foi exibido.\"\n )\n : t(\n \"remoteError.description\",\n \"Verifique a conex\u00E3o e tente novamente.\"\n )\n }}\n </span>\n </div>\n <button mat-stroked-button type=\"button\" (click)=\"retryRemoteData()\">\n {{ t(\"remoteError.retry\", \"Tentar novamente\") }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0 && !(error$ | async)) {\n <div\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n >\n @if (emptyStateTemplate(); as empty) {\n @if (\n simpleRichContentNodes(empty, {\n imageAlt: config.templating?.emptyState?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (empty.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"empty.value\"\n [ngClass]=\"empty.class\"\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [style.cssText]=\"\n (empty.style ? empty.style + ';' : '') +\n iconStyle(empty.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n >\n <img\n [src]=\"empty.value\"\n [alt]=\"config.templating?.emptyState?.imageAlt || ''\"\n />\n @if (empty.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(empty.badge?.color)\n ? empty.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (empty.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(empty.badge?.color, empty.badge?.variant)\n \"\n >{{ empty.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [ngClass]=\"[\n empty.class || '',\n (empty.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(empty.color, empty.variant) +\n (empty.style ? ';' + empty.style : '')\n \"\n >{{ empty.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">\n @for (\n _ of ratingRange(empty);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, empty.value)\"\n [color]=\"ratingThemeColor(empty)\"\n [style.cssText]=\"ratingIconStyle(empty)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n [innerHTML]=\"empty.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"empty\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"empty\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"empty\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">{{\n empty.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n }\n\n <ng-template\n #rowLayoutNode\n let-node\n let-slot=\"slot\"\n let-imageAlt=\"imageAlt\"\n >\n @if (\n simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt });\n as richNodes\n ) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"[\n slot === 'leading' ? 'leading-icon' : '',\n node?.class || '',\n ]\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\n slot === 'leading'\n ? leadingIconStyle(node?.color, node?.style)\n : (node?.style || '' ? node.style + ';' : '') +\n iconStyle(node?.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n >\n <img\n [src]=\"node?.value\"\n [alt]=\"node?.imageAlt || imageAlt || ''\"\n />\n @if (node?.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(node?.badge?.color)\n ? node?.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (node?.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(node?.badge?.color, node?.badge?.variant)\n \"\n >\n {{ node?.badge?.value }}\n </mat-chip>\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [ngClass]=\"[\n node?.class || '',\n (node?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(node?.color, node?.variant) +\n (node?.style ? ';' + node.style : '')\n \"\n >\n {{ node?.value }}\n </mat-chip>\n }\n @case (\"rating\") {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @for (_ of ratingRange(node); track $index; let idx = $index) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, node?.value)\"\n [color]=\"ratingThemeColor(node)\"\n [style.cssText]=\"ratingIconStyle(node)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n [innerHTML]=\"node?.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"node\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"node\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"node\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @if (\n slot === \"meta\" && config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\n }\n </ng-template>\n\n <ng-template #featureContent let-item let-feature=\"feature\">\n @if (featureTemplateNode(item, feature); as featureNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: featureNode,\n slot: 'feature',\n imageAlt: feature?.imageAlt || '',\n }\n \"\n ></ng-container>\n } @else if (featureRichContentNodes(item, feature); as featureNodes) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (feature.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"feature.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"feature.class\" [style.cssText]=\"feature.style\">\n @for (line of featureLabelLines(item, feature.expr); track $index) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, feature.expr, feature.class);\n as progress\n ) {\n <span class=\"feature-progress\" aria-hidden=\"true\">\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\n </ng-template>\n\n <ng-template\n #listRowLayout\n let-item\n let-index=\"index\"\n let-sectionKey=\"sectionKey\"\n let-clickable=\"clickable\"\n >\n <div\n class=\"list-item-content\"\n [ngClass]=\"rowLayoutItemClass(item)\"\n [attr.style]=\"rowLayoutItemStyle(item)\"\n >\n @if (clickable) {\n <button\n type=\"button\"\n class=\"list-row-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, index) : null\n \"\n (click)=\"onRowActivate(item, index, sectionKey)\"\n ></button>\n }\n @for (\n column of rowLayoutColumns();\n track rowLayoutTrackColumn($index, column)\n ) {\n <div\n [attr.data-row-slot]=\"column.slot\"\n [ngClass]=\"rowLayoutColumnClass(column)\"\n [attr.style]=\"rowLayoutColumnStyle(column)\"\n >\n @if (column.slot === \"leading\") {\n @if (rowLayoutSlot(item, column.slot); as lead) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: lead,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n } @else if (column.slot === \"trailing\") {\n @if (rowLayoutSlot(item, column.slot); as trailingNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: trailingNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"rowActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #rowActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, index)\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n } @else if (column.slot === \"actions\") {\n @if ((visibleActions(item, \"actions\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"actions\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n } @else if (column.slot === \"expand\") {\n @if (showExpandIcon(\"expand\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n } @else if (rowLayoutSlot(item, column.slot); as slotNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: slotNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- List variant -->\n @if (isListVariant()) {\n <!-- Selection and row actions share one neutral list shell so every\n interactive affordance remains a sibling keyboard target. -->\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n\n <!-- Unified list surface -->\n <ng-template #readList>\n @if (isVirtualScrollEnabled()) {\n <cdk-virtual-scroll-viewport\n class=\"praxis-list-virtual-viewport\"\n [itemSize]=\"virtualScrollItemSize()\"\n [minBufferPx]=\"virtualScrollMinBufferPx()\"\n [maxBufferPx]=\"virtualScrollMaxBufferPx()\"\n [style.height]=\"virtualScrollViewportHeight()\"\n >\n <mat-list\n class=\"praxis-list-virtual-list\"\n role=\"list\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n <mat-list-item\n *cdkVirtualFor=\"\n let item of virtualScrollItems(sections$ | async, items$ | async);\n let i = index;\n trackBy: trackByVirtualItem\n \"\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n </mat-list>\n </cdk-virtual-scroll-viewport>\n } @else {\n <mat-list\n role=\"list\"\n [class.praxis-list-bounded-viewport]=\"hasBoundedScrollViewport()\"\n [style.max-height]=\"hasBoundedScrollViewport() ? virtualScrollViewportHeight() : null\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section);\n let sidx = $index\n ) {\n @if (section.key) {\n <div class=\"section-header mat-subheader\">\n @if (sectionHeaderTemplate(section.key); as sh) {\n @if (\n simpleRichContentNodes(sh, {\n imageAlt:\n config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (sh.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"sh.value\"\n [ngClass]=\"sh.class\"\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') +\n iconStyle(sh.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n >\n <img\n [src]=\"sh.value\"\n [alt]=\"\n config.templating?.sectionHeader?.imageAlt || ''\n \"\n />\n @if (sh.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(sh.badge?.color)\n ? sh.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (sh.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(sh.badge?.color, sh.badge?.variant)\n \"\n >{{ sh.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [ngClass]=\"[\n sh.class || '',\n (sh.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(sh.color, sh.variant) +\n (sh.style ? ';' + sh.style : '')\n \"\n >{{ sh.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">\n @for (\n _ of ratingRange(sh);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, sh.value)\"\n [color]=\"ratingThemeColor(sh)\"\n [style.cssText]=\"ratingIconStyle(sh)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n [innerHTML]=\"sh.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"sh\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"sh\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"sh\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">{{\n sh.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n @for (\n item of section.items;\n track trackByItem($index, item);\n let i = $index\n ) {\n <mat-list-item\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider\n role=\"presentation\"\n aria-hidden=\"true\"\n ></mat-divider>\n }\n }\n }\n </mat-list>\n }\n </ng-template>\n\n <ng-template #listItemBody let-item let-i=\"index\" let-sectionKey=\"sectionKey\">\n <div\n class=\"list-row-shell\"\n [class.list-row-shell--selectable]=\"isSelectionEnabled()\"\n [class.list-row-shell--with-control]=\"shouldShowSelectionControl()\"\n [class.list-row-shell--selected]=\"isItemSelected(item)\"\n [class.list-row-shell--expanded]=\"isExpandable() && isExpanded(item, i)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: sectionKey,\n clickable: true,\n }\n \"\n ></ng-container>\n } @else {\n <div\n class=\"list-item-content\"\n [ngClass]=\"itemRuleClass(item)\"\n [attr.style]=\"itemRuleStyle(item)\"\n >\n <button\n type=\"button\"\n class=\"list-item-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, i) : null\n \"\n (click)=\"\n onRowActivate(item, i, sectionKey)\n \"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt:\n config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"\n config.templating?.leading?.imageAlt ||\n ''\n \"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(lead.color, lead.variant)\n \"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(item)?.class\"\n [style.cssText]=\"primary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(primary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(item)\"\n ></praxis-list-metric>\n } @else if (primary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(item)\"\n ></praxis-list-compose>\n } @else if (primary(item)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(item)\"\n ></praxis-list-runtime-component>\n } @else if (primary(item)?.type === \"html\") {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(item)?.class\"\n [style.cssText]=\"secondary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(secondary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (\n item.segmentVariant &&\n item.segmentLabel &&\n item.accountType &&\n item.since\n ) {\n <!-- Component-based rendering for executive items -->\n <span class=\"exec-subline\">\n <praxis-executive-badge\n [variant]=\"item.segmentVariant\"\n [label]=\"item.segmentLabel\"\n ></praxis-executive-badge>\n <span class=\"exec-subcopy\">{{\n item.accountType\n }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\"\n >Desde {{ item.since }}</span\n >\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span\n [innerHTML]=\"secondary(item)?.value\"\n ></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\n } @else if (secondary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(item)\"\n ></praxis-list-compose>\n } @else if (\n secondary(item)?.type === \"component\"\n ) {\n <praxis-list-runtime-component\n [component]=\"secondary(item)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (meta(item); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: item, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n </div>\n </button>\n <div class=\"list-item-trailing\">\n @if (meta(item); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, { slot: \"meta\" });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(m.color, m.variant)\n \"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"m.value\"\n [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon\n [praxisIcon]=\"mpi2\"\n ></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(item); as tr) {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt:\n config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr.color, tr.variant)\n \"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt ||\n ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n @if (\n item.alertsData !== undefined &&\n item.ownerName\n ) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts\n [alerts]=\"item.alertsData\"\n ></praxis-executive-alerts>\n <praxis-executive-owner\n [name]=\"item.ownerName\"\n ></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, i)\n ? 'expand_less'\n : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon()\n ? isExpanded(item, i)\n : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n action.icon || 'more_horiz'\n \"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, i)\"\n [style.cssText]=\"\n actionIconStyle(action.color)\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'stroked')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'raised')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant ||\n action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'flat')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"itemActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #itemActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, i)\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (shouldShowSelectionControl()) {\n <div class=\"list-selection-control\">\n @if (config.selection?.mode === \"multiple\") {\n <mat-checkbox\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, $event.checked)\"\n ></mat-checkbox>\n } @else {\n <mat-radio-button\n [name]=\"selectionControlName()\"\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, true)\"\n ></mat-radio-button>\n }\n </div>\n }\n </div>\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\n [ngClass]=\"expansionRenderingClasses()\"\n [style]=\"expansionRenderingStyle()\"\n [id]=\"expandRegionId(item, i)\"\n role=\"region\"\n [attr.aria-label]=\"expansionRegionAriaLabel(item)\"\n >\n <div class=\"item-expansion-grid\">\n @for (\n expansionSection of expansionSections(item);\n track expansionSection.id\n ) {\n <section\n class=\"expansion-section\"\n [attr.data-section-type]=\"expansionSection.type\"\n >\n @if (expansionSection.title) {\n <div class=\"expansion-section-title\">\n {{ expansionSection.title }}\n </div>\n }\n @if (\n expansionSectionHasContent(\n item,\n expansionSection,\n i\n )\n ) {\n @switch (expansionSection.type) {\n @case (\"chip-list\") {\n <div class=\"expansion-chip-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <mat-chip class=\"expansion-chip\">{{\n expansionItemLabel(expansionEntry)\n }}</mat-chip>\n }\n </div>\n }\n @case (\"timeline\") {\n <div class=\"expansion-timeline\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-timeline-item\">\n <div class=\"expansion-timeline-title\">\n {{\n expansionTimelineTitle(expansionEntry)\n }}\n </div>\n @if (\n expansionTimelineMeta(expansionEntry)\n ) {\n <div class=\"expansion-timeline-meta\">\n {{\n expansionTimelineMeta(\n expansionEntry\n )\n }}\n </div>\n }\n @if (\n expansionTimelineDescription(\n expansionEntry\n )\n ) {\n <div\n class=\"expansion-timeline-description\"\n >\n {{\n expansionTimelineDescription(\n expansionEntry\n )\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n @case (\"key-value\") {\n <dl class=\"expansion-key-value\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-key-value-row\">\n @if (\n expansionKeyValueKey(expansionEntry)\n ) {\n <dt>\n {{\n expansionKeyValueKey(expansionEntry)\n }}\n </dt>\n }\n <dd>\n {{\n expansionKeyValueValue(expansionEntry)\n }}\n </dd>\n </div>\n }\n </dl>\n }\n @case (\"rich-content\") {\n @if (\n expansionRichContentDocument(\n item,\n expansionSection,\n i\n );\n as richExpansionDocument\n ) {\n <praxis-rich-content\n [document]=\"richExpansionDocument\"\n [context]=\"\n expansionRichContentContext(\n item,\n expansionSection,\n i\n )\n \"\n [hostCapabilities]=\"\n expansionRichContentHostCapabilities(\n item,\n expansionSection,\n i\n )\n \"\n rootClassName=\"praxis-list-expansion-rich-content\"\n ></praxis-rich-content>\n }\n }\n @default {\n <div class=\"expansion-info-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-info-item\">\n <div class=\"expansion-info-title\">\n {{ expansionInfoTitle(expansionEntry) }}\n </div>\n @if (expansionInfoValue(expansionEntry)) {\n <div class=\"expansion-info-value\">\n {{\n expansionInfoValue(expansionEntry)\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n }\n } @else {\n <div class=\"expansion-empty\">\n {{\n expansionSection.emptyLabel ||\n \"Sem dados dispon\u00EDveis\"\n }}\n </div>\n }\n </section>\n }\n </div>\n </div>\n }\n </ng-template>\n } @else if (isTilesVariant()) {\n <ng-container *ngTemplateOutlet=\"tilesVariant\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"cardsVariant\"></ng-container>\n }\n\n <!-- Cards variant -->\n <ng-template #cardsVariant>\n <div class=\"cards-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-card\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"list-item-content card-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (detail of detailSlots; track detail.slot) {\n <div\n class=\"card-detail\"\n [ngClass]=\"'card-detail--' + detail.slot\"\n >\n <span class=\"card-detail__label\">{{\n detail.label\n }}</span>\n <span class=\"card-detail__value\">\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: detail.node,\n slot: detail.slot,\n imageAlt: rowLayoutImageAlt(detail.slot),\n }\n \"\n ></ng-container>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n <div class=\"list-item-trailing\">\n @if (meta(it); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (config.templating?.metaPrefixIcon; as mpi2) {\n <mat-icon [praxisIcon]=\"mpi2\"></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"status-overlay\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n } @else {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt || ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Tiles variant -->\n <ng-template #tilesVariant>\n <div class=\"tiles-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-tile\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"tile-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"image\") {\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\n \"\n ></mat-icon>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n }\n </div>\n\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"tile-status\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n }\n }\n\n <div class=\"tile-body\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n\n @if (meta(it); as m) {\n <div\n class=\"tile-meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"m\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ m.value }}</span>\n }\n }\n }\n </div>\n }\n\n @if (featuresVisible()) {\n <div class=\"tiles-features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n\n @if (trailing(it); as tr2) {\n @if (\n !(\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr2?.type === \"chip\" || tr2?.type === \"icon\")\n )\n ) {\n <div\n class=\"tile-trailing\"\n [ngClass]=\"tr2.class\"\n [style.cssText]=\"tr2.style\"\n >\n @if (\n simpleRichContentNodes(tr2, {\n imageAlt: tr2.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [ngClass]=\"\n (tr2.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr2.color, tr2.variant)\n \"\n >{{ tr2.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr2.value\"\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr2.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"tr2.value\"\n [alt]=\"tr2.imageAlt || ''\"\n /></span>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr2);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr2.value)\"\n [color]=\"ratingThemeColor(tr2)\"\n [style.cssText]=\"ratingIconStyle(tr2)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr2.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr2\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr2\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr2\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr2.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n\n @if ((visibleActions(it, \"trailing\") || []).length) {\n <div\n class=\"tile-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Remote pagination stays attached to the collection footer. -->\n @if (isRemoteDataMode() && !(error$ | async)) {\n @if (page$ | async; as ps) {\n @if (total$ | async; as total) {\n @if (config.ui?.showRange === false) {\n <div class=\"list-paginator-total\" aria-live=\"polite\">\n {{ remoteTotalLabel(total) }}\n </div>\n }\n <mat-paginator\n [length]=\"total || 0\"\n [pageIndex]=\"ps.pageNumber || 0\"\n [pageSize]=\"ps.pageSize || config.layout?.pageSize || 10\"\n [pageSizeOptions]=\"listPageSizeOptions()\"\n [selectConfig]=\"paginatorSelectConfig\"\n [showFirstLastButtons]=\"true\"\n [class.hide-range]=\"config.ui?.showRange === false\"\n (page)=\"onPageChange($event)\"\n >\n </mat-paginator>\n }\n }\n }\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block}.praxis-list-root{container-type:inline-size;--p-list-radius: var(--md-sys-shape-corner-medium, 16px);--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-blur: 10px;--p-list-surface: var(--md-sys-color-surface-container);--p-list-surface-low: var(--md-sys-color-surface);--p-list-surface-high: var( --md-sys-color-surface-container-high, var(--md-sys-color-surface-container) );--p-list-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-accent: var(--md-sys-color-primary);--p-list-accent-weak: var(--md-sys-color-primary-container);--p-list-item-surface: var( --md-sys-color-surface-container-low, var(--md-sys-color-surface) );--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--p-list-item-hover-surface: var(--md-sys-color-surface-container-low);--p-list-item-active-surface: var(--md-sys-color-surface-container);--p-list-item-selected-surface: var(--md-sys-color-surface-container);--p-list-grad-from: var(--md-sys-color-primary-container);--p-list-grad-to: var(--md-sys-color-tertiary-container);--p-list-grad-angle: 135deg;--p-list-grad-foreground: var( --md-sys-color-on-primary-container, var(--md-sys-color-on-surface) );--p-list-grad-foreground-muted: color-mix( in srgb, var(--p-list-grad-foreground) 76%, transparent );--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--p-list-trailing-max-width: 320px;--p-list-item-gap: 10px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 10px;--p-list-item-stack-gap: 0px;--p-list-meta-size: .875rem;--p-list-meta-weight: 500;--p-list-chip-height: 22px;--p-list-chip-font-size: 12px;--p-list-trailing-padding-right: 8px;--p-list-action-button-height: 32px;--p-list-tile-minW: 240px;--p-list-tile-gap: 12px;--p-list-tile-padding: 12px;--p-list-tile-radius: 12px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;--p-list-tile-hover-overlay: .04;--p-list-tile-press-overlay: .08;--p-list-tile-press-scale: .99}.list-assistant{display:flex;justify-content:flex-end;gap:8px;padding:4px 4px 8px}.action-loading{opacity:.65}.action-spinner{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}.action-loading .mat-mdc-button-touch-target,.action-loading .mdc-button__label{opacity:.7}.skin-elevated,.skin-outline,.skin-flat,.skin-neumorphism{--p-list-item-surface: var( --mdc-elevated-card-container-color, var(--p-list-surface) );--p-list-item-border: var(--p-list-border)}.skin-elevated .item-card,.skin-outline .item-card,.skin-flat .item-card,.skin-neumorphism .item-card{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:var(--p-list-radius);box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .item-tile,.skin-outline .item-tile,.skin-flat .item-tile,.skin-neumorphism .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .mat-mdc-list-item .list-item-content,.skin-outline .mat-mdc-list-item .list-item-content,.skin-flat .mat-mdc-list-item .list-item-content,.skin-neumorphism .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * .75);box-shadow:var(--p-list-shadow);border:var(--p-list-item-border);color:var(--p-list-foreground)}.skin-outline{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline)}.skin-flat{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline-variant)}.skin-neumorphism{--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-radius: 1.25rem}.skin-pill-soft .item-card,.skin-pill-soft .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border)}.skin-pill-soft .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border);color:var(--p-list-foreground)}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted);--p-list-item-hover-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-active-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-selected-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) )}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-gradient-tile .tile-media{background:color-mix(in srgb,var(--md-sys-color-surface) 74%,transparent);border-color:color-mix(in srgb,var(--p-list-foreground) 22%,transparent)}.skin-gradient-tile .tile-media mat-icon,.skin-gradient-tile .tile-meta,.skin-gradient-tile .tile-trailing,.skin-gradient-tile .feature,.skin-gradient-tile .secondary,.skin-gradient-tile .meta{color:var(--p-list-foreground-muted)}.skin-gradient-tile .tile-status,.skin-gradient-tile [data-rich-node-type=badge] .prx-rich-badge{color:var(--md-sys-color-on-secondary-container, var(--p-list-foreground));background:var(--md-sys-color-secondary-container, rgba(255, 255, 255, .72))}.skin-gradient-tile .mat-mdc-list-item .list-item-content{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-glass .item-card,.skin-glass .item-tile{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.skin-glass .mat-mdc-list-item .list-item-content{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.density-compact .mat-mdc-list-item,.density-compact .item-card{--p-list-item-padding-y: 6px;--p-list-item-padding-x: 10px;--p-list-item-gap: 8px}.density-comfortable .mat-mdc-list-item,.density-comfortable .item-card{--p-list-item-padding-y: 8px;--p-list-item-padding-x: 12px;--p-list-item-gap: 10px}.praxis-list-root.lines-3 .mat-mdc-list-item{min-height:68px}.density-compact{--p-list-tile-gap: 10px;--p-list-tile-padding: 10px;--p-list-tile-minW: 188px}.density-comfortable{--p-list-tile-gap: 12px;--p-list-tile-padding: 12px}.item-spacing-none{--p-list-item-stack-gap: 0px}.item-spacing-tight{--p-list-item-stack-gap: 4px;--p-list-tile-gap: 10px}.item-spacing-default{--p-list-item-stack-gap: 6px;--p-list-tile-gap: 12px}.item-spacing-relaxed{--p-list-item-stack-gap: 14px;--p-list-tile-gap: 20px}.list-item-content{box-sizing:border-box;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),min(34vw,var(--p-list-trailing-max-width)));align-items:center;gap:var(--p-list-item-gap);padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x);width:100%;min-width:0;border-radius:calc(var(--p-list-radius) * .75);overflow:visible}.list-item-content--row-layout{--p-list-row-template-columns: var(--p-list-leading-width) minmax(0, 1fr) minmax(var(--p-list-trailing-min-width), max-content);--p-list-row-gap: var(--p-list-item-gap);--p-list-row-align-items: center;grid-template-columns:var(--p-list-row-template-columns);gap:var(--p-list-row-gap);align-items:var(--p-list-row-align-items);position:relative}.list-row-main-action{position:absolute;inset:0;z-index:1;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer}.list-row-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{position:relative;z-index:0;min-width:0;height:100%;align-self:stretch;display:flex;align-items:var(--p-list-row-slot-align-items, center);gap:8px}.list-item-content--row-layout :is(.list-row-slot--actions,.list-row-slot--expand,.list-row-slot--trailing){z-index:2}.list-item-content--row-layout .list-row-slot>praxis-rich-content,.list-item-content--row-layout .list-row-slot>praxis-list-metric,.list-item-content--row-layout .list-row-slot>praxis-list-compose,.list-item-content--row-layout .list-row-slot>praxis-list-runtime-component{min-width:0}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary,.list-row-slot--identity{min-width:0}.list-row-slot--identity>praxis-list-compose,.list-row-slot--primary>praxis-list-compose,.list-row-slot--secondary>praxis-list-compose{width:100%}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:nowrap;justify-content:flex-end;gap:8px}.list-row-slot .primary,.list-row-slot .secondary,.list-row-slot .meta,.list-row-slot .trailing{min-width:0}.list-item-main-action{grid-column:1/3;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr);align-items:center;gap:var(--p-list-item-gap);min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.list-item-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:12px}.list-item-leading{display:flex;align-items:center;justify-content:center;min-width:0;min-height:100%}.list-item-leading>praxis-rich-content,.list-row-slot--leading>praxis-rich-content{min-width:0;max-width:100%}:host ::ng-deep .list-item-leading [data-rich-node-type=icon],:host ::ng-deep .list-row-slot--leading [data-rich-node-type=icon]{width:36px;height:36px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 14%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 28%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary, #06b6d4));box-sizing:border-box;flex-shrink:0}.leading-placeholder{width:24px;height:24px;display:inline-block}.list-item-text{min-width:0;display:grid;align-content:center;gap:2px}.list-item-trailing{box-sizing:border-box;min-width:0;width:100%;max-width:var(--p-list-trailing-max-width);display:flex;flex-wrap:nowrap;align-self:center;align-content:center;align-items:center;justify-content:end;gap:8px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-trailing>*{align-self:center}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{width:max-content;justify-self:end;align-self:center;display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap;max-width:100%;min-height:var(--p-list-action-button-height)}.list-item-actions .mat-mdc-button-base{min-height:var(--p-list-action-button-height);height:var(--p-list-action-button-height);display:inline-flex;align-items:center}.expand-toggle{color:var(--p-list-foreground-muted)}.mat-mdc-list-item .list-item-content{background:var(--p-list-item-surface);border:var(--p-list-item-border);transition:background .15s ease,box-shadow .15s ease,transform .15s ease}.mat-mdc-list-item{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-item.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-three-lines,.mat-mdc-list-item-single-line,.mat-mdc-list-item-two-line,.mat-mdc-list-item-three-line{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item{min-height:40px}.density-comfortable .mat-mdc-list-item{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text{display:block!important;width:100%!important;height:auto!important;padding:0!important;margin:0!important;overflow:visible!important;box-sizing:border-box}.mat-mdc-list-item{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list mat-list-item:not(:last-child),.praxis-list-root .mat-mdc-list-item:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:var(--p-list-radius, 12px);box-shadow:var(--p-list-shadow, 0 1px 3px rgba(0, 0, 0, .2))}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item:hover .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item:hover .list-item-content{border-color:var(--md-sys-color-primary, #6750a4);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0, 0, 0, .25))}.praxis-list-root[data-item-appearance=capsule] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-capsule .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:9999px;box-shadow:var(--p-list-shadow, none)}.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-item-content,.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-row-shell--selectable,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-row-shell--selectable{background:transparent;border:none;box-shadow:none;border-radius:0}.mat-mdc-list-item:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-shell{width:100%;min-width:0}.list-row-shell--selectable{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;border-radius:calc(var(--p-list-radius) * .75);background:var(--p-list-item-surface);border:var(--p-list-item-border);color:var(--p-list-foreground);overflow:hidden;transition:background .15s ease,box-shadow .15s ease,border-color .15s ease}.list-row-shell--selectable.list-row-shell--with-control{grid-template-columns:minmax(0,1fr) auto}.list-selection-control{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:center;padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x) var(--p-list-item-padding-y) 0}.list-selection-control mat-radio-button{--mat-radio-selected-icon-color: var(--p-list-foreground);--mat-radio-selected-hover-icon-color: var(--p-list-foreground);--mat-radio-selected-focus-icon-color: var(--p-list-foreground);--mat-radio-selected-pressed-icon-color: var(--p-list-foreground);--mat-radio-checked-ripple-color: var(--p-list-foreground)}.praxis-list-root .mat-mdc-list-item .list-row-shell--selectable .list-item-content{background:transparent;border:0;border-radius:0;box-shadow:none}.mat-mdc-list-item:hover .list-row-shell--selectable{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-row-shell--selectable{background:var(--p-list-item-active-surface)}.list-row-shell--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.skin-elevated .list-row-shell--selectable,.skin-outline .list-row-shell--selectable,.skin-flat .list-row-shell--selectable,.skin-neumorphism .list-row-shell--selectable{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-item-border);box-shadow:var(--p-list-shadow)}.skin-pill-soft .list-row-shell--selectable{border-radius:calc(var(--p-list-radius) * 1.3);background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-border);box-shadow:var(--md-sys-elevation-level1)}.skin-gradient-tile .list-row-shell--selectable{border-radius:var(--p-list-radius);background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));color:var(--p-list-foreground)}.skin-glass .list-row-shell--selectable{border-radius:var(--p-list-radius);background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.executive-inline-skin{--p-list-leading-width: 56px;--p-list-trailing-min-width: 232px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 8px;--p-list-item-gap: 10px;--p-list-surface: #f8fafb;--p-list-surface-low: #ffffff;--p-list-item-surface: #ffffff;--p-list-item-hover-surface: #f7fafc;--p-list-item-active-surface: #eef4f8;--p-list-item-selected-surface: #eef4f8;--p-list-foreground: #17324d;--p-list-foreground-muted: #72849a}.executive-inline-skin .list-item-content--row-layout.exec-row-layout{min-height:72px;padding:12px 20px;background:linear-gradient(180deg,#fff,#fbfcfd)!important;border:1px solid #dce5ec!important;border-radius:18px;box-shadow:0 1px 2px #0f223a08,0 4px 14px #0f223a08!important;color:#17324d!important}.executive-inline-skin .mat-mdc-list-item:hover .list-item-content--row-layout.exec-row-layout{background:linear-gradient(180deg,#fff,#f7fafc)!important}.executive-inline-skin .list-item-content--row-layout.exec-row-layout+.item-expansion{margin-left:10px;margin-right:10px}.executive-inline-skin .list-item-content--row-layout.exec-row-layout .list-row-slot{min-height:34px}.executive-inline-skin .list-row-slot--leading{justify-content:center}.executive-inline-skin .list-row-slot--identity{align-items:center;padding-right:4px}.executive-inline-skin .list-row-slot--balance,.executive-inline-skin .list-row-slot--limit,.executive-inline-skin .list-row-slot--risk,.executive-inline-skin .list-row-slot--alerts{justify-content:center;padding-inline:2px}.executive-inline-skin .list-row-slot--owner{justify-content:flex-start;padding-left:0}.executive-inline-skin .list-row-slot--actions{justify-content:flex-end;padding-left:0}.executive-inline-skin .list-row-slot--expand{justify-content:center}.executive-inline-skin .docs-expansion-leading{width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center;border-radius:15px;background:linear-gradient(180deg,#edf4f9,#e6eef5);color:#1b5f86;font-size:1rem;font-weight:800;letter-spacing:.02em;box-shadow:0 1px 3px #1b5f861f;border:1px solid #dbe7f0}.executive-inline-skin .exec-balance-metric,.executive-inline-skin .exec-limit-metric,.executive-inline-skin .exec-risk-metric{min-width:0}.executive-inline-skin .exec-balance-metric .p-list-metric,.executive-inline-skin .exec-limit-metric .p-list-metric,.executive-inline-skin .exec-risk-metric .p-list-metric{gap:5px}.executive-inline-skin .exec-balance-metric .p-list-metric__label,.executive-inline-skin .exec-limit-metric .p-list-metric__label,.executive-inline-skin .exec-risk-metric .p-list-metric__label{font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#8090a1}.executive-inline-skin .exec-balance-metric .p-list-metric__value,.executive-inline-skin .exec-limit-metric .p-list-metric__value{font-size:.96rem;font-weight:800;letter-spacing:-.02em;color:#0d1f34;line-height:1.05}.executive-inline-skin .exec-limit-metric .p-list-metric__caption{font-size:.66rem;font-weight:700;color:#8090a1}.executive-inline-skin .exec-limit-metric .p-list-metric__progress{width:68px;justify-self:center;height:3px}.executive-inline-skin .exec-risk-metric{min-width:84px}.executive-inline-skin .exec-risk-metric .p-list-metric{justify-items:center}.executive-inline-skin .exec-risk-metric .p-list-metric__main{gap:6px}.executive-inline-skin .exec-risk-metric .p-list-metric__value{font-size:1.02rem;font-weight:800;letter-spacing:-.024em;line-height:1}.executive-inline-skin .exec-risk-metric .p-list-metric__progress{width:56px;justify-self:center;height:3px}.executive-inline-skin .exec-risk-metric .p-list-metric__caption{font-size:.7rem;font-weight:700;line-height:1.1}.executive-inline-skin .exec-risk-metric .p-list-metric__caption--below-progress{justify-self:center;margin-top:-1px}.executive-inline-skin .exec-risk-metric .p-list-metric__icon mat-icon{width:15px;height:15px;font-size:15px}.executive-inline-skin .list-item-actions{gap:6px;flex-wrap:nowrap}.executive-inline-skin .list-row-slot--actions .list-item-actions{justify-content:flex-end}.executive-inline-skin .list-item-actions button,.executive-inline-skin .expand-toggle{width:30px;height:30px;min-width:30px;border-radius:12px;color:#6d7f93!important}.executive-inline-skin .list-item-actions button mat-icon,.executive-inline-skin .expand-toggle mat-icon{width:18px;height:18px;font-size:18px}.executive-inline-skin .item-expansion{position:relative;margin-top:-10px;padding:22px 26px;background:linear-gradient(180deg,#fcfdfe,#f5f8fb);border-color:#e4eaf0;border-radius:0 0 22px 22px;box-shadow:inset 0 1px #ffffffdb}.lead-image{position:relative;width:96px;height:72px;border-radius:12px;overflow:hidden}.lead-image img{width:100%;height:100%;object-fit:cover;display:block}.lead-image .lead-badge{position:absolute;left:8px;bottom:8px}.inline-image{position:relative;width:20px;height:20px;border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.inline-image img{width:100%;height:100%;object-fit:cover;display:block}.inline-image .inline-badge{position:absolute;left:2px;bottom:2px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-media .list-item-content{gap:16px}.model-media .item-card{--p-list-leading-width: 136px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.model-hotel .item-card{--p-list-leading-width: 160px}.primary,.secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.primary{-webkit-line-clamp:1;font-weight:600;color:var(--p-list-foreground)}.secondary{-webkit-line-clamp:1;color:var(--p-list-foreground-muted)}.lines-3 .tertiary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-tile .primary{-webkit-line-clamp:2;font-size:.95rem;line-height:1.25rem}.item-tile .secondary{-webkit-line-clamp:2;font-size:.8rem;line-height:1.1rem}.tertiary{color:var(--p-list-foreground-muted)}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:inherit}.feature{display:inline-flex;align-items:center;gap:6px}.feature-line{display:block}.feature-progress{display:block;width:88px;height:4px;margin-top:6px;border-radius:999px;background:#dbe5eb;overflow:hidden}.feature-progress__value{display:block;height:100%;border-radius:inherit;background:#2f9b69}.meta{color:var(--p-list-foreground);font-size:var(--p-list-meta-size);font-weight:var(--p-list-meta-weight);font-variant-numeric:tabular-nums;max-width:100%;min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta>span,.meta praxis-rich-content{min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta .mat-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;line-height:1;vertical-align:middle}.trailing{color:var(--p-list-foreground-muted);margin-left:0;max-width:100%;min-width:0;display:inline-flex;justify-content:flex-end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trailing praxis-rich-content{min-width:0}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:2px 10px;border-radius:999px;font-size:.72rem;font-weight:600;letter-spacing:.02em;border:1px solid var(--p-list-chip-border-color, transparent);background:var(--p-list-chip-background, var(--md-sys-color-primary-container, #e8def8));color:var(--p-list-chip-color, var(--md-sys-color-on-primary-container, #21005d));line-height:18px}.section-header{display:block;font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.section-header praxis-rich-content{display:block;width:100%}.section-header--setup{margin:8px 12px 12px;padding:14px 16px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:color-mix(in srgb,var(--p-list-surface) 92%,var(--md-sys-color-primary) 8%);color:var(--p-list-foreground);font-weight:500}.praxis-list-root mat-list{display:block;padding-bottom:12px}.praxis-list-root .mat-divider{margin-left:var(--p-list-item-padding-x);margin-right:var(--p-list-item-padding-x)}.item-expansion{margin:0 var(--p-list-item-padding-x) var(--p-list-item-stack-gap);padding:var(--p-list-expansion-padding, 14px 16px);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.praxis-list-root[data-item-appearance=card] .list-row-shell--expanded .list-item-content,.praxis-list-root.item-appearance-card .list-row-shell--expanded .list-item-content{border-bottom-left-radius:0;border-bottom-right-radius:0}.praxis-list-root[data-item-appearance=card] .item-expansion--attached,.praxis-list-root.item-appearance-card .item-expansion--attached{margin:0;border-top:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--p-list-radius, 12px);border-bottom-right-radius:var(--p-list-radius, 12px);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--p-list-surface)) 82%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 65%,transparent)}.skin-glass .item-expansion--attached{backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.item-expansion--detached,.item-expansion--modal{margin-top:var(--p-list-item-stack-gap);background:var(--md-sys-color-surface-container, var(--p-list-surface));box-shadow:var(--md-sys-elevation-level1)}.item-expansion--modal{border-color:var(--md-sys-color-outline);box-shadow:var(--md-sys-elevation-level3)}.item-expansion-grid{display:grid;grid-template-columns:var(--p-list-expansion-columns, repeat(auto-fit, minmax(220px, 1fr)));gap:var(--p-list-expansion-gap, 16px)}.expansion-section{min-width:0;display:grid;gap:10px;align-content:start}.expansion-section-title{font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-info-list,.expansion-timeline,.expansion-key-value{display:grid;gap:10px}.expansion-info-item,.expansion-timeline-item{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--p-list-item-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent 28%)}.expansion-info-title,.expansion-timeline-title{font-size:.92rem;font-weight:600;color:var(--p-list-foreground)}.expansion-info-value,.expansion-timeline-meta,.expansion-timeline-description,.expansion-empty{font-size:.82rem;line-height:1.45;color:var(--p-list-foreground-muted)}.expansion-chip-list{display:flex;flex-wrap:wrap;gap:8px}.expansion-chip{background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant)}.expansion-key-value{margin:0;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 16px}.expansion-key-value-row{display:grid;gap:2px;padding:6px 10px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest, rgba(255, 255, 255, .04)) 45%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 45%,transparent)}.expansion-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.68rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.85rem;font-weight:600;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, max(300px, var(--p-list-tile-minW)))), 1fr)));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, var(--p-list-tile-minW))), 1fr)));gap:var(--p-list-tile-gap)}.item-tile{position:relative;display:flex;flex-direction:column;gap:10px;padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);background:var(--p-list-surface);border:var(--p-list-border);color:var(--p-list-foreground);cursor:pointer;min-height:160px;transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out}.item-tile:hover{box-shadow:var(--md-sys-elevation-level2);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-tile:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.tile-main-action{display:flex;flex:1;min-width:0;flex-direction:column;gap:10px;color:inherit;cursor:pointer}.tile-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant);display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover;display:block}.tile-media mat-icon{font-size:28px;height:28px;width:28px;color:var(--p-list-foreground-muted)}.tile-body{display:grid;gap:6px;min-width:0}.tile-meta{display:inline-flex;align-items:center;gap:6px;font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile-trailing{font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap}.tiles-features{display:flex;flex-wrap:wrap;gap:8px;color:inherit}.tile-status{position:absolute;top:10px;right:10px}.tile-actions{position:absolute;top:8px;left:8px;display:flex;gap:4px;opacity:0;pointer-events:none;transform:translateY(-2px);transition:opacity .16s ease-out,transform .16s ease-out}.item-tile:hover .tile-actions,.item-tile:focus-within .tile-actions{opacity:1;pointer-events:auto;transform:translateY(0)}@media(hover:none){.tile-actions{opacity:1;pointer-events:auto;transform:none}}@media(max-width:600px){.tiles-grid,.cards-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}@media(prefers-reduced-motion:reduce){.item-tile,.tile-actions{transition:none}.item-tile:active{transform:none}.item-card{transition:none}.item-card:active{transform:none}}.item-card{padding:max(var(--p-list-tile-padding),16px);display:flex;flex-direction:column;gap:var(--p-list-item-gap);min-height:var(--p-list-card-minH, 220px);position:relative;cursor:pointer;background:var(--p-list-surface);border:var(--p-list-border);border-radius:var(--p-list-tile-radius);box-shadow:var(--p-list-shadow);transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out;--p-list-leading-width: 96px;--p-list-trailing-min-width: 0px}.density-compact .item-card{min-height:var(--p-list-card-minH, 148px)}.pdx-list-item--primary{--p-list-item-rule-tone: var(--md-sys-color-primary, #06b6d4);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 52%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--success{--p-list-item-rule-tone: var(--p-color-success, #10b981);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 48%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--warning{--p-list-item-rule-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) );border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 54%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 10%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--danger{--p-list-item-rule-tone: var(--md-sys-color-error, #ef4444);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 56%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 11%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--muted{opacity:.78;border-style:dashed!important;background:color-mix(in srgb,var(--md-sys-color-surface-variant) 34%,var(--p-list-surface))!important}.pdx-list-item--neutral{border-color:var(--md-sys-color-outline-variant)!important;background:var(--p-list-surface)!important}.card-main-action{display:block;width:100%;min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.card-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.item-card .list-item-content{display:block;padding:0;min-width:0;overflow:hidden}.item-card .list-item-leading{position:absolute;top:18px;left:18px;min-height:0;z-index:1}.item-card .leading-placeholder{width:36px;height:36px}.item-card .leading-icon.mat-icon,.item-card .list-item-leading>mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent));color:var(--md-sys-color-primary)}.item-card .list-item-text{display:grid;gap:9px;padding-left:50px;width:100%;min-width:0;box-sizing:border-box}.item-card .primary{padding-right:min(50%,160px);font-size:1rem;font-weight:800;letter-spacing:-.01em;line-height:1.18;min-width:0;overflow-wrap:anywhere}.item-card .secondary{color:var(--p-list-foreground-muted);font-weight:600;line-height:1.35;min-width:0;overflow-wrap:anywhere}.item-card .features{display:flex;flex-direction:column;gap:8px;margin-top:2px}.item-card .feature{display:inline-flex;align-items:start;gap:8px;min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .feature mat-icon{margin-top:1px;color:var(--p-list-foreground-muted);opacity:.86}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width);grid-column:1/-1;align-items:stretch;padding-right:0}.card-detail-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px;margin-top:16px}.card-detail{min-width:0;padding:11px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 22%,transparent),color-mix(in srgb,var(--p-list-surface) 92%,transparent));box-shadow:inset 0 1px #ffffff14}.card-detail__label{display:block;margin-bottom:3px;color:var(--p-list-foreground-muted);font-size:.68rem;font-weight:700;letter-spacing:.08em;line-height:1.1;text-transform:uppercase}.card-detail__value{display:block;min-width:0;color:var(--p-list-foreground);font-size:.94rem;font-weight:800;line-height:1.2;overflow-wrap:normal;word-break:normal}.card-detail__value,.card-detail__value *{white-space:nowrap}.card-detail--balance .card-detail__value{color:var(--md-sys-color-primary)}.card-detail--limit .card-detail__value{color:var(--md-sys-color-error)}.card-detail--risk .card-detail__value{color:var(--md-sys-color-tertiary, var(--p-list-foreground))}.item-card:hover{box-shadow:var(--md-sys-elevation-level3);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-card:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.card-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:6px 8px 4px;border-top:1px solid var(--md-sys-color-outline-variant);margin-top:auto}.status-overlay{position:absolute;top:14px;right:14px;max-width:min(42%,148px);overflow:hidden;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto;width:100%;min-width:0;max-width:100%}.status-overlay .mdc-evolution-chip__text-label,.status-overlay .mat-mdc-chip-action-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.leading-icon.mat-icon,.list-item-leading>mat-icon,.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon],[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon]{width:36px;height:36px;min-width:36px;line-height:36px;font-size:19px;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;box-sizing:border-box;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 15%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 30%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary));box-shadow:inset 0 1px #ffffff0f}.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon,[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon{font-size:19px;width:19px;height:19px;line-height:19px;color:inherit}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);--mdc-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mdc-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );font-size:var(--p-list-chip-font-size);font-weight:600;letter-spacing:.02em;border-radius:999px!important;background-color:var(--p-list-chip-background, var(--md-sys-color-surface-container-high))!important;color:var(--p-list-chip-color, var(--md-sys-color-on-surface))!important;border:1px solid var(--p-list-chip-border-color, transparent)!important}:host ::ng-deep .mat-mdc-chip .mdc-evolution-chip__text-label,:host ::ng-deep .mat-mdc-chip .mat-mdc-chip-action-label{color:var(--p-list-chip-color, inherit)!important;font-weight:600;font-size:.72rem;letter-spacing:.02em}.meta .mat-icon{font-size:18px;height:18px;width:18px}.features{overflow:hidden}@keyframes shimmer{0%{background-position:-468px 0}to{background-position:468px 0}}.skeleton{animation-duration:1.2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear;background:linear-gradient(to right,var(--md-sys-color-surface-container-low) 8%,var(--md-sys-color-surface-container) 18%,var(--md-sys-color-surface-container-low) 33%);background-size:800px 104px;position:relative}.skeleton-avatar{width:32px;height:32px;border-radius:50%}.skeleton-line{height:10px;margin:6px 0;border-radius:6px}.skeleton-chip{width:48px;height:18px;border-radius:999px}.chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important;color:var(--p-list-chip-color, currentColor)!important}.w-60{width:60%}.w-40{width:40%}.list-collection-toolbar{display:flex;align-items:center;gap:12px;padding:12px;margin-bottom:8px;color:var(--p-list-foreground);background:var(--p-list-surface-low);border:var(--p-list-border);border-radius:calc(var(--p-list-radius) * .75)}.list-toolbar-search{flex:1 1 320px;min-width:220px;max-width:440px}.list-toolbar-commands{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;margin-inline-start:auto}.list-toolbar-commands button{border-radius:8px}.list-toolbar-commands button .mat-icon{margin-right:6px}.list-toolbar-sort{width:200px}.list-remote-error{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;margin:8px 4px 0;padding:16px;color:var(--md-sys-color-on-error-container);background:var(--md-sys-color-error-container);border-radius:calc(var(--p-list-radius) * .75)}.list-remote-error__copy{display:flex;flex-direction:column;gap:4px;min-width:0}.list-remote-error__copy span{color:color-mix(in srgb,var(--md-sys-color-on-error-container) 82%,transparent);line-height:1.45}.list-remote-error button{color:var(--md-sys-color-on-error-container);--mat-button-outlined-label-text-color: var( --md-sys-color-on-error-container );--mat-button-outlined-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent );--mdc-outlined-button-label-text-color: var( --md-sys-color-on-error-container );--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent )}.mat-mdc-paginator{margin-top:14px;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--p-list-surface-low);color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-container{min-height:40px;padding:4px 8px;gap:6px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select{margin-left:8px;width:92px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-text-field-wrapper{--mdc-outlined-text-field-container-color: color-mix( in srgb, var(--p-list-surface-low) 92%, var(--md-sys-color-on-surface) 8% );--mdc-outlined-text-field-input-text-color: var(--p-list-foreground);min-height:40px;padding-inline:12px 8px;background:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;background-color:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;color:var(--p-list-foreground)!important}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-form-field-infix{min-height:40px;padding-block:8px;width:auto}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-select-trigger{min-height:24px;padding-right:2px;color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-range-label,:host ::ng-deep .mat-mdc-paginator .mat-mdc-select-value-text{font-size:12px;color:var(--p-list-foreground-muted)}.list-paginator-total{margin-top:14px;padding:4px 8px 0;font-size:12px;color:var(--p-list-foreground-muted)}:host ::ng-deep .mat-mdc-paginator.hide-range .mat-mdc-paginator-range-label{display:none}::ng-deep .praxis-list-paginator-select-panel.mat-mdc-select-panel{--mat-select-panel-background-color: var( --md-sys-color-surface-container, var(--mat-sys-surface-container) );background:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;background-color:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #d7dbe5) 70%,transparent);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, #000) 28%,transparent)}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option{--mat-option-label-text-color: var(--md-sys-color-on-surface, #111827);color:var(--md-sys-color-on-surface, #111827)!important}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option.mat-mdc-option-active{--mat-option-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-primary, #2f7cff) 14%, transparent );background:color-mix(in srgb,var(--md-sys-color-primary, #2f7cff) 14%,transparent)!important;color:var(--md-sys-color-on-surface, #111827)!important}.muted{color:var(--p-list-foreground-muted)}@container (max-width: 720px){.executive-inline-skin .list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.executive-inline-skin .list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--primary,.executive-inline-skin .list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.executive-inline-skin .list-item-content--row-layout .list-row-slot--meta,.executive-inline-skin .list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.executive-inline-skin .list-selection-control{padding-left:0}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.executive-inline-skin .list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.executive-inline-skin .list-item-trailing .list-item-actions{margin-inline-start:auto}.executive-inline-skin .item-expansion{margin-left:0;margin-right:0}.executive-inline-skin .list-collection-toolbar{flex-direction:column;align-items:stretch}.executive-inline-skin .list-toolbar-search,.executive-inline-skin .list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.executive-inline-skin .list-toolbar-commands{width:100%;margin-inline-start:0}.executive-inline-skin .list-toolbar-sort{flex:1 1 100%}.executive-inline-skin .list-toolbar-commands button{flex:0 0 auto}.executive-inline-skin .list-remote-error{grid-template-columns:auto minmax(0,1fr)}.executive-inline-skin .list-remote-error button{grid-column:1/-1;justify-self:stretch}}@container (max-width: 420px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}@media(max-width:640px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}.list-loading-status{display:flex;align-items:center;gap:8px;padding:12px 0;color:inherit;--mat-progress-spinner-active-indicator-color: currentColor}.list-loading-status:empty{display:none}.praxis-list-virtual-viewport,.praxis-list-bounded-viewport{display:block;width:100%;overflow-y:auto;outline:none;padding-right:4px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent) transparent}.praxis-list-virtual-viewport::-webkit-scrollbar,.praxis-list-bounded-viewport::-webkit-scrollbar{width:6px;height:6px}.praxis-list-virtual-viewport::-webkit-scrollbar-track,.praxis-list-bounded-viewport::-webkit-scrollbar-track{background:transparent}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent);border-radius:999px}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb:hover,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, #94a3b8) 72%,transparent)}.praxis-list-virtual-viewport{height:var(--p-list-viewport-height, 400px);contain:strict}.praxis-list-virtual-viewport .praxis-list-virtual-list{padding-top:0;padding-bottom:0}.list-item-menu-trigger{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--md-sys-shape-corner-full, 9999px);color:var(--p-list-foreground-muted, inherit);transition:background-color .15s ease,color .15s ease}.list-item-menu-trigger:hover{background-color:var(--p-list-item-hover-surface, rgba(0, 0, 0, .04));color:var(--p-list-foreground, inherit)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i2$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i2$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3.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: MatRadioModule }, { kind: "component", type: i4$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: i7.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i8.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i8.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i11.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4$2.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$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }, { kind: "component", type: ExecutiveBadgeComponent, selector: "praxis-executive-badge", inputs: ["ariaLabel", "label", "variant"] }, { kind: "component", type: ExecutiveAlertsComponent, selector: "praxis-executive-alerts", inputs: ["alerts"] }, { kind: "component", type: ExecutiveOwnerComponent, selector: "praxis-executive-owner", inputs: ["name"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }, { kind: "component", type: PraxisListMetricComponent, selector: "praxis-list-metric", inputs: ["metric"] }, { kind: "component", type: PraxisListComposeComponent, selector: "praxis-list-compose", inputs: ["compose"] }, { kind: "component", type: PraxisListRuntimeComponentComponent, selector: "praxis-list-runtime-component", inputs: ["component"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i15.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i15.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i15.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13357
|
+
], viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"list-loading-status\" role=\"status\">\n @if (loading$ | async) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\" aria-hidden=\"true\"></mat-progress-spinner>\n <span>{{ t('loading', 'Carregando itens\u2026') }}</span>\n }\n</div>\n<div\n class=\"praxis-list-root\"\n tabindex=\"-1\"\n [attr.aria-busy]=\"(loading$ | async) ? 'true' : 'false'\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.data-item-appearance]=\"config?.layout?.itemAppearance || null\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (enableCustomization) {\n <div class=\"list-assistant\">\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openConfigEditor()\"\n [matTooltip]=\"configEditorLabel()\"\n [attr.aria-label]=\"configEditorLabel()\"\n data-testid=\"praxis-list-open-config-editor\"\n >\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openAiAssistant()\"\n matTooltip=\"Copiloto semantico Praxis\"\n aria-label=\"Abrir copiloto semantico Praxis da lista\"\n data-testid=\"praxis-list-ai-assistant-trigger\"\n >\n <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"\n aiAssistantViewState.state === 'processing' ||\n aiAssistantViewState.state === 'applying'\n \"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-list-ai-assistant\"\n panelTestId=\"praxis-list-ai-assistant-panel\"\n submitTestId=\"praxis-list-ai-assistant-submit\"\n applyTestId=\"praxis-list-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n\n @if (\n config.export?.enabled ||\n (isRemoteDataMode() &&\n (config.ui?.showSort ||\n (config.ui?.showSearch && config.ui?.searchField)))\n ) {\n <div\n class=\"list-collection-toolbar\"\n role=\"group\"\n [attr.aria-label]=\"t('toolbar.label', 'Controles da lista')\"\n >\n @if (\n isRemoteDataMode() && config.ui?.showSearch && config.ui?.searchField\n ) {\n <mat-form-field\n class=\"list-toolbar-search\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{\n config.ui?.searchPlaceholder || t(\"toolbar.search\", \"Buscar\")\n }}</mat-label>\n <mat-icon matPrefix [praxisIcon]=\"'search'\"></mat-icon>\n <input\n #searchInput\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n\n <div class=\"list-toolbar-commands\">\n @if (isRemoteDataMode() && config.ui?.showSort) {\n <mat-form-field\n class=\"list-toolbar-sort\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{ t(\"toolbar.sort\", \"Ordenar por\") }}</mat-label>\n @let activeSort = activeSortValue((page$ | async)?.sort);\n <mat-select\n [value]=\"activeSort\"\n (selectionChange)=\"onSortChange($event.value)\"\n >\n @if (activeSort && !hasSortOption(activeSort)) {\n <mat-option [value]=\"activeSort\">{{ activeSort }}</mat-option>\n }\n @for (op of config.ui?.sortOptions || []; track $index) {\n <mat-option [value]=\"sortOptionValue(op)\">{{\n sortOptionLabel(op)\n }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (config.export?.enabled) {\n <button\n mat-stroked-button\n type=\"button\"\n [matMenuTriggerFor]=\"listExportMenu\"\n [attr.aria-label]=\"t('export.button', 'Exportar')\"\n [disabled]=\"exportBusy\"\n [attr.aria-busy]=\"exportBusy\"\n >\n <mat-icon [praxisIcon]=\"'download'\"></mat-icon>\n {{ t(\"export.button\", \"Exportar\") }}\n </button>\n <span class=\"cdk-visually-hidden\" aria-live=\"polite\">\n {{ exportStatusMessage }}\n </span>\n <mat-menu #listExportMenu=\"matMenu\">\n @for (format of listExportFormats(); track format) {\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"onExportAction(format)\"\n >\n <mat-icon [praxisIcon]=\"exportIcon(format)\"></mat-icon>\n {{ format.toUpperCase() }}\n </button>\n }\n </mat-menu>\n }\n </div>\n </div>\n }\n\n <!-- Skeleton while loading -->\n @if (loading$ | async) {\n @if (hasSkeleton()) {\n @if (isListVariant()) {\n <mat-list>\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <mat-list-item>\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else {\n <div class=\"cards-grid\">\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (error$ | async; as remoteError) {\n <div class=\"list-remote-error\" role=\"alert\">\n <mat-icon [praxisIcon]=\"'error_outline'\"></mat-icon>\n <div class=\"list-remote-error__copy\">\n <strong>{{\n t(\"remoteError.title\", \"N\u00E3o foi poss\u00EDvel carregar a lista\")\n }}</strong>\n <span>\n {{\n remoteError.filtered\n ? t(\n \"remoteError.filteredDescription\",\n \"Os filtros permanecem aplicados. Nenhum dado sem filtro foi exibido.\"\n )\n : t(\n \"remoteError.description\",\n \"Verifique a conex\u00E3o e tente novamente.\"\n )\n }}\n </span>\n </div>\n <button mat-stroked-button type=\"button\" (click)=\"retryRemoteData()\">\n {{ t(\"remoteError.retry\", \"Tentar novamente\") }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0 && !(error$ | async)) {\n @if (hasCustomEmptyStateTemplate()) {\n <div\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n >\n @if (emptyStateTemplate(); as empty) {\n @if (\n simpleRichContentNodes(empty, {\n imageAlt: config.templating?.emptyState?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (empty.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"empty.value\"\n [ngClass]=\"empty.class\"\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [style.cssText]=\"\n (empty.style ? empty.style + ';' : '') +\n iconStyle(empty.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n >\n <img\n [src]=\"empty.value\"\n [alt]=\"config.templating?.emptyState?.imageAlt || ''\"\n />\n @if (empty.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(empty.badge?.color)\n ? empty.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (empty.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(empty.badge?.color, empty.badge?.variant)\n \"\n >{{ empty.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [ngClass]=\"[\n empty.class || '',\n (empty.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(empty.color, empty.variant) +\n (empty.style ? ';' + empty.style : '')\n \"\n >{{ empty.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">\n @for (\n _ of ratingRange(empty);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, empty.value)\"\n [color]=\"ratingThemeColor(empty)\"\n [style.cssText]=\"ratingIconStyle(empty)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n [innerHTML]=\"empty.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"empty\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"empty\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"empty\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">{{\n empty.value\n }}</span>\n }\n }\n }\n }\n </div>\n } @else {\n <praxis-empty-state-card\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n [icon]=\"emptyStateIcon()\"\n [title]=\"emptyStateTitle()\"\n [description]=\"emptyStateDescription()\"\n [primaryAction]=\"emptyStatePrimaryAction()\"\n [secondaryActions]=\"emptyStateSecondaryActions()\"\n />\n }\n }\n }\n\n <ng-template\n #rowLayoutNode\n let-node\n let-slot=\"slot\"\n let-imageAlt=\"imageAlt\"\n >\n @if (\n simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt });\n as richNodes\n ) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"[\n slot === 'leading' ? 'leading-icon' : '',\n node?.class || '',\n ]\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\n slot === 'leading'\n ? leadingIconStyle(node?.color, node?.style)\n : (node?.style || '' ? node.style + ';' : '') +\n iconStyle(node?.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n >\n <img\n [src]=\"node?.value\"\n [alt]=\"node?.imageAlt || imageAlt || ''\"\n />\n @if (node?.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(node?.badge?.color)\n ? node?.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (node?.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(node?.badge?.color, node?.badge?.variant)\n \"\n >\n {{ node?.badge?.value }}\n </mat-chip>\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [ngClass]=\"[\n node?.class || '',\n (node?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(node?.color, node?.variant) +\n (node?.style ? ';' + node.style : '')\n \"\n >\n {{ node?.value }}\n </mat-chip>\n }\n @case (\"rating\") {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @for (_ of ratingRange(node); track $index; let idx = $index) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, node?.value)\"\n [color]=\"ratingThemeColor(node)\"\n [style.cssText]=\"ratingIconStyle(node)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n [innerHTML]=\"node?.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"node\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"node\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"node\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @if (\n slot === \"meta\" && config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\n }\n </ng-template>\n\n <ng-template #featureContent let-item let-feature=\"feature\">\n @if (featureTemplateNode(item, feature); as featureNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: featureNode,\n slot: 'feature',\n imageAlt: feature?.imageAlt || '',\n }\n \"\n ></ng-container>\n } @else if (featureRichContentNodes(item, feature); as featureNodes) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (feature.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"feature.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"feature.class\" [style.cssText]=\"feature.style\">\n @for (line of featureLabelLines(item, feature.expr); track $index) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, feature.expr, feature.class);\n as progress\n ) {\n <span class=\"feature-progress\" aria-hidden=\"true\">\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\n </ng-template>\n\n <ng-template\n #listRowLayout\n let-item\n let-index=\"index\"\n let-sectionKey=\"sectionKey\"\n let-clickable=\"clickable\"\n >\n <div\n class=\"list-item-content\"\n [ngClass]=\"rowLayoutItemClass(item)\"\n [attr.style]=\"rowLayoutItemStyle(item)\"\n >\n @if (clickable) {\n <button\n type=\"button\"\n class=\"list-row-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, index) : null\n \"\n (click)=\"onRowActivate(item, index, sectionKey)\"\n ></button>\n }\n @for (\n column of rowLayoutColumns();\n track rowLayoutTrackColumn($index, column)\n ) {\n <div\n [attr.data-row-slot]=\"column.slot\"\n [ngClass]=\"rowLayoutColumnClass(column)\"\n [attr.style]=\"rowLayoutColumnStyle(column)\"\n >\n @if (column.slot === \"leading\") {\n @if (rowLayoutSlot(item, column.slot); as lead) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: lead,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n } @else if (column.slot === \"trailing\") {\n @if (rowLayoutSlot(item, column.slot); as trailingNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: trailingNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"rowActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #rowActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, index)\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n } @else if (column.slot === \"actions\") {\n @if ((visibleActions(item, \"actions\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"actions\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n } @else if (column.slot === \"expand\") {\n @if (showExpandIcon(\"expand\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n } @else if (rowLayoutSlot(item, column.slot); as slotNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: slotNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- List variant -->\n @if (isListVariant()) {\n <!-- Selection and row actions share one neutral list shell so every\n interactive affordance remains a sibling keyboard target. -->\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n\n <!-- Unified list surface -->\n <ng-template #readList>\n @if (isVirtualScrollEnabled()) {\n <cdk-virtual-scroll-viewport\n class=\"praxis-list-virtual-viewport\"\n [itemSize]=\"virtualScrollItemSize()\"\n [minBufferPx]=\"virtualScrollMinBufferPx()\"\n [maxBufferPx]=\"virtualScrollMaxBufferPx()\"\n [style.height]=\"virtualScrollViewportHeight()\"\n >\n <mat-list\n class=\"praxis-list-virtual-list\"\n role=\"list\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n <mat-list-item\n *cdkVirtualFor=\"\n let item of virtualScrollItems(sections$ | async, items$ | async);\n let i = index;\n trackBy: trackByVirtualItem\n \"\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n </mat-list>\n </cdk-virtual-scroll-viewport>\n } @else {\n <mat-list\n role=\"list\"\n [class.praxis-list-bounded-viewport]=\"hasBoundedScrollViewport()\"\n [style.max-height]=\"hasBoundedScrollViewport() ? virtualScrollViewportHeight() : null\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section);\n let sidx = $index\n ) {\n @if (section.key) {\n <div class=\"section-header mat-subheader\">\n @if (sectionHeaderTemplate(section.key); as sh) {\n @if (\n simpleRichContentNodes(sh, {\n imageAlt:\n config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (sh.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"sh.value\"\n [ngClass]=\"sh.class\"\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') +\n iconStyle(sh.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n >\n <img\n [src]=\"sh.value\"\n [alt]=\"\n config.templating?.sectionHeader?.imageAlt || ''\n \"\n />\n @if (sh.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(sh.badge?.color)\n ? sh.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (sh.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(sh.badge?.color, sh.badge?.variant)\n \"\n >{{ sh.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [ngClass]=\"[\n sh.class || '',\n (sh.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(sh.color, sh.variant) +\n (sh.style ? ';' + sh.style : '')\n \"\n >{{ sh.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">\n @for (\n _ of ratingRange(sh);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, sh.value)\"\n [color]=\"ratingThemeColor(sh)\"\n [style.cssText]=\"ratingIconStyle(sh)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n [innerHTML]=\"sh.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"sh\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"sh\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"sh\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">{{\n sh.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n @for (\n item of section.items;\n track trackByItem($index, item);\n let i = $index\n ) {\n <mat-list-item\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider\n role=\"presentation\"\n aria-hidden=\"true\"\n ></mat-divider>\n }\n }\n }\n </mat-list>\n }\n </ng-template>\n\n <ng-template #listItemBody let-item let-i=\"index\" let-sectionKey=\"sectionKey\">\n <div\n class=\"list-row-shell\"\n [class.list-row-shell--selectable]=\"isSelectionEnabled()\"\n [class.list-row-shell--with-control]=\"shouldShowSelectionControl()\"\n [class.list-row-shell--selected]=\"isItemSelected(item)\"\n [class.list-row-shell--expanded]=\"isExpandable() && isExpanded(item, i)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: sectionKey,\n clickable: true,\n }\n \"\n ></ng-container>\n } @else {\n <div\n class=\"list-item-content\"\n [ngClass]=\"itemRuleClass(item)\"\n [attr.style]=\"itemRuleStyle(item)\"\n >\n <button\n type=\"button\"\n class=\"list-item-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, i) : null\n \"\n (click)=\"\n onRowActivate(item, i, sectionKey)\n \"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt:\n config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"\n config.templating?.leading?.imageAlt ||\n ''\n \"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(lead.color, lead.variant)\n \"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(item)?.class\"\n [style.cssText]=\"primary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(primary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(item)\"\n ></praxis-list-metric>\n } @else if (primary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(item)\"\n ></praxis-list-compose>\n } @else if (primary(item)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(item)\"\n ></praxis-list-runtime-component>\n } @else if (primary(item)?.type === \"html\") {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(item)?.class\"\n [style.cssText]=\"secondary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(secondary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (\n item.segmentVariant &&\n item.segmentLabel &&\n item.accountType &&\n item.since\n ) {\n <!-- Component-based rendering for executive items -->\n <span class=\"exec-subline\">\n <praxis-executive-badge\n [variant]=\"item.segmentVariant\"\n [label]=\"item.segmentLabel\"\n ></praxis-executive-badge>\n <span class=\"exec-subcopy\">{{\n item.accountType\n }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\"\n >Desde {{ item.since }}</span\n >\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span\n [innerHTML]=\"secondary(item)?.value\"\n ></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\n } @else if (secondary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(item)\"\n ></praxis-list-compose>\n } @else if (\n secondary(item)?.type === \"component\"\n ) {\n <praxis-list-runtime-component\n [component]=\"secondary(item)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (meta(item); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: item, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n </div>\n </button>\n <div class=\"list-item-trailing\">\n @if (meta(item); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, { slot: \"meta\" });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(m.color, m.variant)\n \"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"m.value\"\n [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon\n [praxisIcon]=\"mpi2\"\n ></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(item); as tr) {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt:\n config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr.color, tr.variant)\n \"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt ||\n ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n @if (\n item.alertsData !== undefined &&\n item.ownerName\n ) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts\n [alerts]=\"item.alertsData\"\n ></praxis-executive-alerts>\n <praxis-executive-owner\n [name]=\"item.ownerName\"\n ></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, i)\n ? 'expand_less'\n : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon()\n ? isExpanded(item, i)\n : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n action.icon || 'more_horiz'\n \"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, i)\"\n [style.cssText]=\"\n actionIconStyle(action.color)\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'stroked')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'raised')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant ||\n action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'flat')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"itemActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #itemActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, i)\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (shouldShowSelectionControl()) {\n <div class=\"list-selection-control\">\n @if (config.selection?.mode === \"multiple\") {\n <mat-checkbox\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, $event.checked)\"\n ></mat-checkbox>\n } @else {\n <mat-radio-button\n [name]=\"selectionControlName()\"\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, true)\"\n ></mat-radio-button>\n }\n </div>\n }\n </div>\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\n [ngClass]=\"expansionRenderingClasses()\"\n [style]=\"expansionRenderingStyle()\"\n [id]=\"expandRegionId(item, i)\"\n role=\"region\"\n [attr.aria-label]=\"expansionRegionAriaLabel(item)\"\n >\n <div class=\"item-expansion-grid\">\n @for (\n expansionSection of expansionSections(item);\n track expansionSection.id\n ) {\n <section\n class=\"expansion-section\"\n [attr.data-section-type]=\"expansionSection.type\"\n >\n @if (expansionSection.title) {\n <div class=\"expansion-section-title\">\n {{ expansionSection.title }}\n </div>\n }\n @if (\n expansionSectionHasContent(\n item,\n expansionSection,\n i\n )\n ) {\n @switch (expansionSection.type) {\n @case (\"chip-list\") {\n <div class=\"expansion-chip-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <mat-chip class=\"expansion-chip\">{{\n expansionItemLabel(expansionEntry)\n }}</mat-chip>\n }\n </div>\n }\n @case (\"timeline\") {\n <div class=\"expansion-timeline\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-timeline-item\">\n <div class=\"expansion-timeline-title\">\n {{\n expansionTimelineTitle(expansionEntry)\n }}\n </div>\n @if (\n expansionTimelineMeta(expansionEntry)\n ) {\n <div class=\"expansion-timeline-meta\">\n {{\n expansionTimelineMeta(\n expansionEntry\n )\n }}\n </div>\n }\n @if (\n expansionTimelineDescription(\n expansionEntry\n )\n ) {\n <div\n class=\"expansion-timeline-description\"\n >\n {{\n expansionTimelineDescription(\n expansionEntry\n )\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n @case (\"key-value\") {\n <dl class=\"expansion-key-value\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-key-value-row\">\n @if (\n expansionKeyValueKey(expansionEntry)\n ) {\n <dt>\n {{\n expansionKeyValueKey(expansionEntry)\n }}\n </dt>\n }\n <dd>\n {{\n expansionKeyValueValue(expansionEntry)\n }}\n </dd>\n </div>\n }\n </dl>\n }\n @case (\"rich-content\") {\n @if (\n expansionRichContentDocument(\n item,\n expansionSection,\n i\n );\n as richExpansionDocument\n ) {\n <praxis-rich-content\n [document]=\"richExpansionDocument\"\n [context]=\"\n expansionRichContentContext(\n item,\n expansionSection,\n i\n )\n \"\n [hostCapabilities]=\"\n expansionRichContentHostCapabilities(\n item,\n expansionSection,\n i\n )\n \"\n rootClassName=\"praxis-list-expansion-rich-content\"\n ></praxis-rich-content>\n }\n }\n @default {\n <div class=\"expansion-info-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-info-item\">\n <div class=\"expansion-info-title\">\n {{ expansionInfoTitle(expansionEntry) }}\n </div>\n @if (expansionInfoValue(expansionEntry)) {\n <div class=\"expansion-info-value\">\n {{\n expansionInfoValue(expansionEntry)\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n }\n } @else {\n <div class=\"expansion-empty\">\n {{\n expansionSection.emptyLabel ||\n \"Sem dados dispon\u00EDveis\"\n }}\n </div>\n }\n </section>\n }\n </div>\n </div>\n }\n </ng-template>\n } @else if (isTilesVariant()) {\n <ng-container *ngTemplateOutlet=\"tilesVariant\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"cardsVariant\"></ng-container>\n }\n\n <!-- Cards variant -->\n <ng-template #cardsVariant>\n <div class=\"cards-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-card\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"list-item-content card-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (detail of detailSlots; track detail.slot) {\n <div\n class=\"card-detail\"\n [ngClass]=\"'card-detail--' + detail.slot\"\n >\n <span class=\"card-detail__label\">{{\n detail.label\n }}</span>\n <span class=\"card-detail__value\">\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: detail.node,\n slot: detail.slot,\n imageAlt: rowLayoutImageAlt(detail.slot),\n }\n \"\n ></ng-container>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n <div class=\"list-item-trailing\">\n @if (meta(it); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (config.templating?.metaPrefixIcon; as mpi2) {\n <mat-icon [praxisIcon]=\"mpi2\"></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"status-overlay\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n } @else {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt || ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Tiles variant -->\n <ng-template #tilesVariant>\n <div class=\"tiles-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-tile\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"tile-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"image\") {\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\n \"\n ></mat-icon>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n }\n </div>\n\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"tile-status\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n }\n }\n\n <div class=\"tile-body\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n\n @if (meta(it); as m) {\n <div\n class=\"tile-meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"m\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ m.value }}</span>\n }\n }\n }\n </div>\n }\n\n @if (featuresVisible()) {\n <div class=\"tiles-features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n\n @if (trailing(it); as tr2) {\n @if (\n !(\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr2?.type === \"chip\" || tr2?.type === \"icon\")\n )\n ) {\n <div\n class=\"tile-trailing\"\n [ngClass]=\"tr2.class\"\n [style.cssText]=\"tr2.style\"\n >\n @if (\n simpleRichContentNodes(tr2, {\n imageAlt: tr2.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [ngClass]=\"\n (tr2.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr2.color, tr2.variant)\n \"\n >{{ tr2.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr2.value\"\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr2.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"tr2.value\"\n [alt]=\"tr2.imageAlt || ''\"\n /></span>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr2);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr2.value)\"\n [color]=\"ratingThemeColor(tr2)\"\n [style.cssText]=\"ratingIconStyle(tr2)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr2.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr2\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr2\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr2\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr2.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n\n @if ((visibleActions(it, \"trailing\") || []).length) {\n <div\n class=\"tile-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Remote pagination stays attached to the collection footer. -->\n @if (isRemoteDataMode() && !(error$ | async)) {\n @if (page$ | async; as ps) {\n @if (total$ | async; as total) {\n @if (config.ui?.showRange === false) {\n <div class=\"list-paginator-total\" aria-live=\"polite\">\n {{ remoteTotalLabel(total) }}\n </div>\n }\n <mat-paginator\n [length]=\"total || 0\"\n [pageIndex]=\"ps.pageNumber || 0\"\n [pageSize]=\"ps.pageSize || config.layout?.pageSize || 10\"\n [pageSizeOptions]=\"listPageSizeOptions()\"\n [selectConfig]=\"paginatorSelectConfig\"\n [showFirstLastButtons]=\"true\"\n [class.hide-range]=\"config.ui?.showRange === false\"\n (page)=\"onPageChange($event)\"\n >\n </mat-paginator>\n }\n }\n }\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block}.praxis-list-root{container-type:inline-size;--p-list-radius: var(--md-sys-shape-corner-medium, 16px);--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-blur: 10px;--p-list-surface: var(--md-sys-color-surface-container);--p-list-surface-low: var(--md-sys-color-surface);--p-list-surface-high: var( --md-sys-color-surface-container-high, var(--md-sys-color-surface-container) );--p-list-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-accent: var(--md-sys-color-primary);--p-list-accent-weak: var(--md-sys-color-primary-container);--p-list-item-surface: var( --md-sys-color-surface-container-low, var(--md-sys-color-surface) );--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--p-list-item-hover-surface: var(--md-sys-color-surface-container-low);--p-list-item-active-surface: var(--md-sys-color-surface-container);--p-list-item-selected-surface: var(--md-sys-color-surface-container);--p-list-grad-from: var(--md-sys-color-primary-container);--p-list-grad-to: var(--md-sys-color-tertiary-container);--p-list-grad-angle: 135deg;--p-list-grad-foreground: var( --md-sys-color-on-primary-container, var(--md-sys-color-on-surface) );--p-list-grad-foreground-muted: color-mix( in srgb, var(--p-list-grad-foreground) 76%, transparent );--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--p-list-trailing-max-width: 320px;--p-list-item-gap: 10px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 10px;--p-list-item-stack-gap: 0px;--p-list-meta-size: .875rem;--p-list-meta-weight: 500;--p-list-chip-height: 22px;--p-list-chip-font-size: 12px;--p-list-trailing-padding-right: 8px;--p-list-action-button-height: 32px;--p-list-tile-minW: 240px;--p-list-tile-gap: 12px;--p-list-tile-padding: 12px;--p-list-tile-radius: 12px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;--p-list-tile-hover-overlay: .04;--p-list-tile-press-overlay: .08;--p-list-tile-press-scale: .99}.list-assistant{display:flex;justify-content:flex-end;gap:8px;padding:4px 4px 8px}.action-loading{opacity:.65}.action-spinner{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}.action-loading .mat-mdc-button-touch-target,.action-loading .mdc-button__label{opacity:.7}.skin-elevated,.skin-outline,.skin-flat,.skin-neumorphism{--p-list-item-surface: var( --mdc-elevated-card-container-color, var(--p-list-surface) );--p-list-item-border: var(--p-list-border)}.skin-elevated .item-card,.skin-outline .item-card,.skin-flat .item-card,.skin-neumorphism .item-card{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:var(--p-list-radius);box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .item-tile,.skin-outline .item-tile,.skin-flat .item-tile,.skin-neumorphism .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .mat-mdc-list-item .list-item-content,.skin-outline .mat-mdc-list-item .list-item-content,.skin-flat .mat-mdc-list-item .list-item-content,.skin-neumorphism .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * .75);box-shadow:var(--p-list-shadow);border:var(--p-list-item-border);color:var(--p-list-foreground)}.skin-outline{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline)}.skin-flat{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline-variant)}.skin-neumorphism{--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-radius: 1.25rem}.skin-pill-soft .item-card,.skin-pill-soft .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border)}.skin-pill-soft .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border);color:var(--p-list-foreground)}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted);--p-list-item-hover-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-active-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-selected-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) )}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-gradient-tile .tile-media{background:color-mix(in srgb,var(--md-sys-color-surface) 74%,transparent);border-color:color-mix(in srgb,var(--p-list-foreground) 22%,transparent)}.skin-gradient-tile .tile-media mat-icon,.skin-gradient-tile .tile-meta,.skin-gradient-tile .tile-trailing,.skin-gradient-tile .feature,.skin-gradient-tile .secondary,.skin-gradient-tile .meta{color:var(--p-list-foreground-muted)}.skin-gradient-tile .tile-status,.skin-gradient-tile [data-rich-node-type=badge] .prx-rich-badge{color:var(--md-sys-color-on-secondary-container, var(--p-list-foreground));background:var(--md-sys-color-secondary-container, rgba(255, 255, 255, .72))}.skin-gradient-tile .mat-mdc-list-item .list-item-content{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-glass .item-card,.skin-glass .item-tile{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.skin-glass .mat-mdc-list-item .list-item-content{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.density-compact .mat-mdc-list-item,.density-compact .item-card{--p-list-item-padding-y: 6px;--p-list-item-padding-x: 10px;--p-list-item-gap: 8px}.density-comfortable .mat-mdc-list-item,.density-comfortable .item-card{--p-list-item-padding-y: 8px;--p-list-item-padding-x: 12px;--p-list-item-gap: 10px}.praxis-list-root.lines-3 .mat-mdc-list-item{min-height:68px}.density-compact{--p-list-tile-gap: 10px;--p-list-tile-padding: 10px;--p-list-tile-minW: 188px}.density-comfortable{--p-list-tile-gap: 12px;--p-list-tile-padding: 12px}.item-spacing-none{--p-list-item-stack-gap: 0px}.item-spacing-tight{--p-list-item-stack-gap: 4px;--p-list-tile-gap: 10px}.item-spacing-default{--p-list-item-stack-gap: 6px;--p-list-tile-gap: 12px}.item-spacing-relaxed{--p-list-item-stack-gap: 14px;--p-list-tile-gap: 20px}.list-item-content{box-sizing:border-box;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),min(34vw,var(--p-list-trailing-max-width)));align-items:center;gap:var(--p-list-item-gap);padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x);width:100%;min-width:0;border-radius:calc(var(--p-list-radius) * .75);overflow:visible}.list-item-content--row-layout{--p-list-row-template-columns: var(--p-list-leading-width) minmax(0, 1fr) minmax(var(--p-list-trailing-min-width), max-content);--p-list-row-gap: var(--p-list-item-gap);--p-list-row-align-items: center;grid-template-columns:var(--p-list-row-template-columns);gap:var(--p-list-row-gap);align-items:var(--p-list-row-align-items);position:relative}.list-row-main-action{position:absolute;inset:0;z-index:1;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer}.list-row-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{position:relative;z-index:0;min-width:0;height:100%;align-self:stretch;display:flex;align-items:var(--p-list-row-slot-align-items, center);gap:8px}.list-item-content--row-layout :is(.list-row-slot--actions,.list-row-slot--expand,.list-row-slot--trailing){z-index:2}.list-item-content--row-layout .list-row-slot>praxis-rich-content,.list-item-content--row-layout .list-row-slot>praxis-list-metric,.list-item-content--row-layout .list-row-slot>praxis-list-compose,.list-item-content--row-layout .list-row-slot>praxis-list-runtime-component{min-width:0}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary,.list-row-slot--identity{min-width:0}.list-row-slot--identity>praxis-list-compose,.list-row-slot--primary>praxis-list-compose,.list-row-slot--secondary>praxis-list-compose{width:100%}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:nowrap;justify-content:flex-end;gap:8px}.list-row-slot .primary,.list-row-slot .secondary,.list-row-slot .meta,.list-row-slot .trailing{min-width:0}.list-item-main-action{grid-column:1/3;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr);align-items:center;gap:var(--p-list-item-gap);min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.list-item-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:12px}.list-item-leading{display:flex;align-items:center;justify-content:center;min-width:0;min-height:100%}.list-item-leading>praxis-rich-content,.list-row-slot--leading>praxis-rich-content{min-width:0;max-width:100%}:host ::ng-deep .list-item-leading [data-rich-node-type=icon],:host ::ng-deep .list-row-slot--leading [data-rich-node-type=icon]{width:36px;height:36px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 14%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 28%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary, #06b6d4));box-sizing:border-box;flex-shrink:0}.leading-placeholder{width:24px;height:24px;display:inline-block}.list-item-text{min-width:0;display:grid;align-content:center;gap:2px}.list-item-trailing{box-sizing:border-box;min-width:0;width:100%;max-width:var(--p-list-trailing-max-width);display:flex;flex-wrap:nowrap;align-self:center;align-content:center;align-items:center;justify-content:end;gap:8px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-trailing>*{align-self:center}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{width:max-content;justify-self:end;align-self:center;display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap;max-width:100%;min-height:var(--p-list-action-button-height)}.list-item-actions .mat-mdc-button-base{min-height:var(--p-list-action-button-height);height:var(--p-list-action-button-height);display:inline-flex;align-items:center}.expand-toggle{color:var(--p-list-foreground-muted)}.mat-mdc-list-item .list-item-content{background:var(--p-list-item-surface);border:var(--p-list-item-border);transition:background .15s ease,box-shadow .15s ease,transform .15s ease}.mat-mdc-list-item{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-item.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-three-lines,.mat-mdc-list-item-single-line,.mat-mdc-list-item-two-line,.mat-mdc-list-item-three-line{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item{min-height:40px}.density-comfortable .mat-mdc-list-item{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text{display:block!important;width:100%!important;height:auto!important;padding:0!important;margin:0!important;overflow:visible!important;box-sizing:border-box}.mat-mdc-list-item{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list mat-list-item:not(:last-child),.praxis-list-root .mat-mdc-list-item:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:var(--p-list-radius, 12px);box-shadow:var(--p-list-shadow, 0 1px 3px rgba(0, 0, 0, .2))}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item:hover .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item:hover .list-item-content{border-color:var(--md-sys-color-primary, #6750a4);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0, 0, 0, .25))}.praxis-list-root[data-item-appearance=capsule] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-capsule .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:9999px;box-shadow:var(--p-list-shadow, none)}.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-item-content,.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-row-shell--selectable,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-row-shell--selectable{background:transparent;border:none;box-shadow:none;border-radius:0}.mat-mdc-list-item:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-shell{width:100%;min-width:0}.list-row-shell--selectable{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;border-radius:calc(var(--p-list-radius) * .75);background:var(--p-list-item-surface);border:var(--p-list-item-border);color:var(--p-list-foreground);overflow:hidden;transition:background .15s ease,box-shadow .15s ease,border-color .15s ease}.list-row-shell--selectable.list-row-shell--with-control{grid-template-columns:minmax(0,1fr) auto}.list-selection-control{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:center;padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x) var(--p-list-item-padding-y) 0}.list-selection-control mat-radio-button{--mat-radio-selected-icon-color: var(--p-list-foreground);--mat-radio-selected-hover-icon-color: var(--p-list-foreground);--mat-radio-selected-focus-icon-color: var(--p-list-foreground);--mat-radio-selected-pressed-icon-color: var(--p-list-foreground);--mat-radio-checked-ripple-color: var(--p-list-foreground)}.praxis-list-root .mat-mdc-list-item .list-row-shell--selectable .list-item-content{background:transparent;border:0;border-radius:0;box-shadow:none}.mat-mdc-list-item:hover .list-row-shell--selectable{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-row-shell--selectable{background:var(--p-list-item-active-surface)}.list-row-shell--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.skin-elevated .list-row-shell--selectable,.skin-outline .list-row-shell--selectable,.skin-flat .list-row-shell--selectable,.skin-neumorphism .list-row-shell--selectable{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-item-border);box-shadow:var(--p-list-shadow)}.skin-pill-soft .list-row-shell--selectable{border-radius:calc(var(--p-list-radius) * 1.3);background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-border);box-shadow:var(--md-sys-elevation-level1)}.skin-gradient-tile .list-row-shell--selectable{border-radius:var(--p-list-radius);background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));color:var(--p-list-foreground)}.skin-glass .list-row-shell--selectable{border-radius:var(--p-list-radius);background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.executive-inline-skin{--p-list-leading-width: 56px;--p-list-trailing-min-width: 232px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 8px;--p-list-item-gap: 10px;--p-list-surface: #f8fafb;--p-list-surface-low: #ffffff;--p-list-item-surface: #ffffff;--p-list-item-hover-surface: #f7fafc;--p-list-item-active-surface: #eef4f8;--p-list-item-selected-surface: #eef4f8;--p-list-foreground: #17324d;--p-list-foreground-muted: #5b6f84;--p-list-chip-background: #eef4f8;--p-list-chip-color: #17324d;--p-list-chip-border-color: #d5e2ec;--md-sys-color-on-surface: #17324d;--md-sys-color-on-surface-variant: #5b6f84;--md-sys-color-surface: #ffffff;--md-sys-color-surface-container-low: #f1f5f9;--md-sys-color-surface-container: #e2e8f0;--md-sys-color-surface-container-high: #e2e8f0;--md-sys-color-surface-container-highest: #cbd5e1;--md-sys-color-outline: #94a3b8;--md-sys-color-outline-variant: #d5e2ec;--praxis-icon-btn-fg: #6d7f93;color:var(--p-list-foreground)}.executive-inline-skin .list-item-content--row-layout.exec-row-layout{min-height:72px;padding:12px 16px;background:linear-gradient(180deg,#fff,#fbfcfd)!important;border:1px solid #dce5ec!important;border-radius:18px;box-shadow:0 1px 2px #0f223a08,0 4px 14px #0f223a08!important;color:#17324d!important}.executive-inline-skin .mat-mdc-list-item:hover .list-item-content--row-layout.exec-row-layout{background:linear-gradient(180deg,#fff,#f7fafc)!important}.executive-inline-skin .list-item-content--row-layout.exec-row-layout+.item-expansion{margin-left:10px;margin-right:10px}.executive-inline-skin .list-item-content--row-layout.exec-row-layout .list-row-slot{min-height:34px}.executive-inline-skin .list-row-slot--leading{justify-content:center}.executive-inline-skin .list-row-slot--identity{align-items:center;padding-right:4px}.executive-inline-skin .list-row-slot--balance,.executive-inline-skin .list-row-slot--limit,.executive-inline-skin .list-row-slot--risk,.executive-inline-skin .list-row-slot--alerts{justify-content:center;padding-inline:2px}.executive-inline-skin .list-row-slot--owner{justify-content:flex-start;padding-left:0}.executive-inline-skin .list-row-slot--actions{justify-content:flex-end;padding-left:0}.executive-inline-skin .list-row-slot--expand{justify-content:center}:host ::ng-deep .executive-inline-skin .docs-expansion-leading{width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center;border-radius:15px;background:linear-gradient(180deg,#edf4f9,#e6eef5);color:#1b5f86;font-size:1rem;font-weight:800;letter-spacing:.02em;box-shadow:0 1px 3px #1b5f861f;border:1px solid #dbe7f0}:host ::ng-deep .executive-inline-skin .exec-balance-metric,:host ::ng-deep .executive-inline-skin .exec-limit-metric,:host ::ng-deep .executive-inline-skin .exec-risk-metric{min-width:0;gap:5px}:host ::ng-deep .executive-inline-skin .exec-balance-metric .p-list-metric__label,:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__label,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__label{font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#8090a1}:host ::ng-deep .executive-inline-skin .exec-balance-metric .p-list-metric__value,:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__value{font-size:.96rem;font-weight:800;letter-spacing:-.02em;color:#0d1f34;line-height:1.05}:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__caption{font-size:.66rem;font-weight:700;color:#8090a1}:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__progress{width:68px;justify-self:center;height:3px}:host ::ng-deep .executive-inline-skin .exec-risk-metric{min-width:84px;justify-items:center}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__main{gap:5px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__value{font-size:1.02rem;font-weight:800;letter-spacing:-.024em;line-height:1}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__progress{width:56px;justify-self:center;height:3px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__caption{font-size:.7rem;font-weight:700;line-height:1.1}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__below-progress,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__caption--below-progress{justify-self:center;margin-top:-1px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__icon mat-icon,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__icon .prx-rich-icon{width:15px;height:15px;font-size:15px}.executive-inline-skin .list-item-actions{gap:6px;flex-wrap:nowrap}.executive-inline-skin .list-row-slot--actions .list-item-actions{justify-content:flex-end}.executive-inline-skin .list-item-actions button,.executive-inline-skin .expand-toggle{--praxis-icon-btn-fg: #6d7f93;width:30px;height:30px;min-width:30px;border-radius:12px;color:#6d7f93!important}.executive-inline-skin .list-item-actions button mat-icon,.executive-inline-skin .expand-toggle mat-icon{width:18px;height:18px;font-size:18px}.executive-inline-skin .item-expansion{position:relative;margin-top:-10px;padding:22px 26px;background:linear-gradient(180deg,#fcfdfe,#f5f8fb);border-color:#e4eaf0;border-radius:0 0 22px 22px;box-shadow:inset 0 1px #ffffffdb;color:var(--p-list-foreground)}.lead-image{position:relative;width:96px;height:72px;border-radius:12px;overflow:hidden}.lead-image img{width:100%;height:100%;object-fit:cover;display:block}.lead-image .lead-badge{position:absolute;left:8px;bottom:8px}.inline-image{position:relative;width:20px;height:20px;border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.inline-image img{width:100%;height:100%;object-fit:cover;display:block}.inline-image .inline-badge{position:absolute;left:2px;bottom:2px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-media .list-item-content{gap:16px}.model-media .item-card{--p-list-leading-width: 136px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.model-hotel .item-card{--p-list-leading-width: 160px}.primary,.secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.primary{-webkit-line-clamp:1;font-weight:600;color:var(--p-list-foreground)}.secondary{-webkit-line-clamp:1;color:var(--p-list-foreground-muted)}.lines-3 .tertiary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-tile .primary{-webkit-line-clamp:2;font-size:.95rem;line-height:1.25rem}.item-tile .secondary{-webkit-line-clamp:2;font-size:.8rem;line-height:1.1rem}.tertiary{color:var(--p-list-foreground-muted)}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:inherit}.feature{display:inline-flex;align-items:center;gap:6px}.feature-line{display:block}.feature-progress{display:block;width:88px;height:4px;margin-top:6px;border-radius:999px;background:#dbe5eb;overflow:hidden}.feature-progress__value{display:block;height:100%;border-radius:inherit;background:#2f9b69}.meta{color:var(--p-list-foreground);font-size:var(--p-list-meta-size);font-weight:var(--p-list-meta-weight);font-variant-numeric:tabular-nums;max-width:100%;min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta>span,.meta praxis-rich-content{min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta .mat-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;line-height:1;vertical-align:middle}.trailing{color:var(--p-list-foreground-muted);margin-left:0;max-width:100%;min-width:0;display:inline-flex;justify-content:flex-end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trailing praxis-rich-content{min-width:0}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:2px 10px;border-radius:999px;font-size:.72rem;font-weight:600;letter-spacing:.02em;border:1px solid var(--p-list-chip-border-color, transparent);background:var(--p-list-chip-background, var(--md-sys-color-primary-container, #e8def8));color:var(--p-list-chip-color, var(--md-sys-color-on-primary-container, #21005d));line-height:18px}.section-header{display:block;font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.section-header praxis-rich-content{display:block;width:100%}.section-header--setup{margin:8px 12px 12px;padding:14px 16px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:color-mix(in srgb,var(--p-list-surface) 92%,var(--md-sys-color-primary) 8%);color:var(--p-list-foreground);font-weight:500}praxis-empty-state-card.section-header,praxis-empty-state-card.section-header--setup{margin:0;padding:0;border:0;border-radius:0;background:transparent;font-size:inherit;font-weight:inherit}.praxis-list-root mat-list{display:block;padding-bottom:12px}.praxis-list-root .mat-divider{margin-left:var(--p-list-item-padding-x);margin-right:var(--p-list-item-padding-x)}.item-expansion{margin:0 var(--p-list-item-padding-x) var(--p-list-item-stack-gap);padding:var(--p-list-expansion-padding, 14px 16px);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75);color:var(--p-list-foreground);white-space:normal;min-width:0}.praxis-list-root[data-item-appearance=card] .list-row-shell--expanded .list-item-content,.praxis-list-root.item-appearance-card .list-row-shell--expanded .list-item-content{border-bottom-left-radius:0;border-bottom-right-radius:0}.praxis-list-root[data-item-appearance=card] .item-expansion--attached,.praxis-list-root.item-appearance-card .item-expansion--attached{margin:0;border-top:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--p-list-radius, 12px);border-bottom-right-radius:var(--p-list-radius, 12px);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--p-list-surface)) 82%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 65%,transparent)}.skin-glass .item-expansion--attached{backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.item-expansion--detached,.item-expansion--modal{margin-top:var(--p-list-item-stack-gap);background:var(--md-sys-color-surface-container, var(--p-list-surface));box-shadow:var(--md-sys-elevation-level1)}.item-expansion--modal{border-color:var(--md-sys-color-outline);box-shadow:var(--md-sys-elevation-level3)}.item-expansion-grid{display:grid;grid-template-columns:var(--p-list-expansion-columns, repeat(auto-fit, minmax(220px, 1fr)));gap:var(--p-list-expansion-gap, 16px)}.expansion-section{min-width:0;display:grid;gap:10px;align-content:start}.expansion-section-title{font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-info-list,.expansion-timeline,.expansion-key-value{display:grid;gap:10px}.expansion-info-item,.expansion-timeline-item{display:grid;gap:4px;min-width:0;padding:10px 12px;border-radius:14px;background:var(--p-list-item-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent 28%)}.expansion-info-title,.expansion-timeline-title{font-size:.92rem;font-weight:600;color:var(--p-list-foreground);white-space:normal;overflow-wrap:break-word}.expansion-info-value,.expansion-timeline-meta,.expansion-timeline-description,.expansion-empty{font-size:.82rem;line-height:1.45;color:var(--p-list-foreground-muted);white-space:normal;overflow-wrap:break-word}.expansion-chip-list{display:flex;flex-wrap:wrap;gap:8px}.expansion-chip{background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant)}.expansion-key-value{margin:0;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 12px}.expansion-key-value-row{display:grid;align-content:start;gap:3px;min-width:0;overflow:hidden;padding:8px 10px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest, rgba(255, 255, 255, .04)) 45%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 45%,transparent)}.expansion-key-value-row dt,.expansion-key-value-row dd{margin:0;min-width:0;white-space:normal;overflow-wrap:break-word}.expansion-key-value-row dt{font-size:.68rem;font-weight:700;line-height:1.25;letter-spacing:.05em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.85rem;font-weight:600;line-height:1.35;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, max(300px, var(--p-list-tile-minW)))), 1fr)));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, var(--p-list-tile-minW))), 1fr)));gap:var(--p-list-tile-gap)}.item-tile{position:relative;display:flex;flex-direction:column;gap:10px;padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);background:var(--p-list-surface);border:var(--p-list-border);color:var(--p-list-foreground);cursor:pointer;min-height:160px;transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out}.item-tile:hover{box-shadow:var(--md-sys-elevation-level2);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-tile:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.tile-main-action{display:flex;flex:1;min-width:0;flex-direction:column;gap:10px;color:inherit;cursor:pointer}.tile-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant);display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover;display:block}.tile-media mat-icon{font-size:28px;height:28px;width:28px;color:var(--p-list-foreground-muted)}.tile-body{display:grid;gap:6px;min-width:0}.tile-meta{display:inline-flex;align-items:center;gap:6px;font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile-trailing{font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap}.tiles-features{display:flex;flex-wrap:wrap;gap:8px;color:inherit}.tile-status{position:absolute;top:10px;right:10px}.tile-actions{position:absolute;top:8px;left:8px;display:flex;gap:4px;opacity:0;pointer-events:none;transform:translateY(-2px);transition:opacity .16s ease-out,transform .16s ease-out}.item-tile:hover .tile-actions,.item-tile:focus-within .tile-actions{opacity:1;pointer-events:auto;transform:translateY(0)}@media(hover:none){.tile-actions{opacity:1;pointer-events:auto;transform:none}}@media(max-width:600px){.tiles-grid,.cards-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}@media(prefers-reduced-motion:reduce){.item-tile,.tile-actions{transition:none}.item-tile:active{transform:none}.item-card{transition:none}.item-card:active{transform:none}}.item-card{padding:max(var(--p-list-tile-padding),16px);display:flex;flex-direction:column;gap:var(--p-list-item-gap);min-height:var(--p-list-card-minH, 220px);position:relative;cursor:pointer;background:var(--p-list-surface);border:var(--p-list-border);border-radius:var(--p-list-tile-radius);box-shadow:var(--p-list-shadow);transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out;--p-list-leading-width: 96px;--p-list-trailing-min-width: 0px}.density-compact .item-card{min-height:var(--p-list-card-minH, 148px)}.pdx-list-item--primary{--p-list-item-rule-tone: var(--md-sys-color-primary, #06b6d4);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 52%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--success{--p-list-item-rule-tone: var(--p-color-success, #10b981);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 48%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--warning{--p-list-item-rule-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) );border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 54%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 10%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--danger{--p-list-item-rule-tone: var(--md-sys-color-error, #ef4444);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 56%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 11%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--muted{opacity:.78;border-style:dashed!important;background:color-mix(in srgb,var(--md-sys-color-surface-variant) 34%,var(--p-list-surface))!important}.pdx-list-item--neutral{border-color:var(--md-sys-color-outline-variant)!important;background:var(--p-list-surface)!important}.card-main-action{display:block;width:100%;min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.card-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.item-card .list-item-content{display:block;padding:0;min-width:0;overflow:hidden}.item-card .list-item-leading{position:absolute;top:18px;left:18px;min-height:0;z-index:1}.item-card .leading-placeholder{width:36px;height:36px}.item-card .leading-icon.mat-icon,.item-card .list-item-leading>mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent));color:var(--md-sys-color-primary)}.item-card .list-item-text{display:grid;gap:9px;padding-left:50px;width:100%;min-width:0;box-sizing:border-box}.item-card .primary{padding-right:min(50%,160px);font-size:1rem;font-weight:800;letter-spacing:-.01em;line-height:1.18;min-width:0;overflow-wrap:anywhere}.item-card .secondary{color:var(--p-list-foreground-muted);font-weight:600;line-height:1.35;min-width:0;overflow-wrap:anywhere}.item-card .features{display:flex;flex-direction:column;gap:8px;margin-top:2px}.item-card .feature{display:inline-flex;align-items:start;gap:8px;min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .feature mat-icon{margin-top:1px;color:var(--p-list-foreground-muted);opacity:.86}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width);grid-column:1/-1;align-items:stretch;padding-right:0}.card-detail-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px;margin-top:16px}.card-detail{min-width:0;padding:11px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 22%,transparent),color-mix(in srgb,var(--p-list-surface) 92%,transparent));box-shadow:inset 0 1px #ffffff14}.card-detail__label{display:block;margin-bottom:3px;color:var(--p-list-foreground-muted);font-size:.68rem;font-weight:700;letter-spacing:.08em;line-height:1.1;text-transform:uppercase}.card-detail__value{display:block;min-width:0;color:var(--p-list-foreground);font-size:.94rem;font-weight:800;line-height:1.2;overflow-wrap:normal;word-break:normal}.card-detail__value,.card-detail__value *{white-space:nowrap}.card-detail--balance .card-detail__value{color:var(--md-sys-color-primary)}.card-detail--limit .card-detail__value{color:var(--md-sys-color-error)}.card-detail--risk .card-detail__value{color:var(--md-sys-color-tertiary, var(--p-list-foreground))}.item-card:hover{box-shadow:var(--md-sys-elevation-level3);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-card:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.card-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:6px 8px 4px;border-top:1px solid var(--md-sys-color-outline-variant);margin-top:auto}.status-overlay{position:absolute;top:14px;right:14px;max-width:min(42%,148px);overflow:hidden;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto;width:100%;min-width:0;max-width:100%}.status-overlay .mdc-evolution-chip__text-label,.status-overlay .mat-mdc-chip-action-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.leading-icon.mat-icon,.list-item-leading>mat-icon,.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon],[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon]{width:36px;height:36px;min-width:36px;line-height:36px;font-size:19px;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;box-sizing:border-box;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 15%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 30%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary));box-shadow:inset 0 1px #ffffff0f}.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon,[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon{font-size:19px;width:19px;height:19px;line-height:19px;color:inherit}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);--mdc-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mat-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mdc-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );--mat-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );--mdc-chip-outline-color: var(--p-list-chip-border-color, transparent);--mat-chip-outline-color: var(--p-list-chip-border-color, transparent);font-size:var(--p-list-chip-font-size);font-weight:600;letter-spacing:.02em;border-radius:999px!important;background-color:var(--p-list-chip-background, var(--md-sys-color-surface-container-high))!important;color:var(--p-list-chip-color, var(--md-sys-color-on-surface))!important;border:1px solid var(--p-list-chip-border-color, transparent)!important}:host ::ng-deep .mat-mdc-chip .mdc-evolution-chip__text-label,:host ::ng-deep .mat-mdc-chip .mat-mdc-chip-action-label{color:var(--p-list-chip-color, inherit)!important;font-weight:600;font-size:.72rem;letter-spacing:.02em}.meta .mat-icon{font-size:18px;height:18px;width:18px}.features{overflow:hidden}@keyframes shimmer{0%{background-position:-468px 0}to{background-position:468px 0}}.skeleton{animation-duration:1.2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear;background:linear-gradient(to right,var(--md-sys-color-surface-container-low) 8%,var(--md-sys-color-surface-container) 18%,var(--md-sys-color-surface-container-low) 33%);background-size:800px 104px;position:relative}.skeleton-avatar{width:32px;height:32px;border-radius:50%}.skeleton-line{height:10px;margin:6px 0;border-radius:6px}.skeleton-chip{width:48px;height:18px;border-radius:999px}.chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important;color:var(--p-list-chip-color, currentColor)!important}.w-60{width:60%}.w-40{width:40%}.list-collection-toolbar{display:flex;align-items:center;gap:12px;padding:12px;margin-bottom:8px;color:var(--p-list-foreground);background:var(--p-list-surface-low);border:var(--p-list-border);border-radius:calc(var(--p-list-radius) * .75)}.list-toolbar-search{flex:1 1 320px;min-width:220px;max-width:440px}.list-toolbar-commands{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;margin-inline-start:auto}.list-toolbar-commands button{border-radius:8px}.list-toolbar-commands button .mat-icon{margin-right:6px}.list-toolbar-sort{width:200px}.list-remote-error{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;margin:8px 4px 0;padding:16px;color:var(--md-sys-color-on-error-container);background:var(--md-sys-color-error-container);border-radius:calc(var(--p-list-radius) * .75)}.list-remote-error__copy{display:flex;flex-direction:column;gap:4px;min-width:0}.list-remote-error__copy span{color:color-mix(in srgb,var(--md-sys-color-on-error-container) 82%,transparent);line-height:1.45}.list-remote-error button{color:var(--md-sys-color-on-error-container);--mat-button-outlined-label-text-color: var( --md-sys-color-on-error-container );--mat-button-outlined-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent );--mdc-outlined-button-label-text-color: var( --md-sys-color-on-error-container );--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent )}.mat-mdc-paginator{margin-top:14px;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--p-list-surface-low);color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-container{min-height:40px;padding:4px 8px;gap:6px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select{margin-left:8px;width:92px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-text-field-wrapper{--mdc-outlined-text-field-container-color: color-mix( in srgb, var(--p-list-surface-low) 92%, var(--md-sys-color-on-surface) 8% );--mdc-outlined-text-field-input-text-color: var(--p-list-foreground);min-height:40px;padding-inline:12px 8px;background:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;background-color:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;color:var(--p-list-foreground)!important}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-form-field-infix{min-height:40px;padding-block:8px;width:auto}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-select-trigger{min-height:24px;padding-right:2px;color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-range-label,:host ::ng-deep .mat-mdc-paginator .mat-mdc-select-value-text{font-size:12px;color:var(--p-list-foreground-muted)}.list-paginator-total{margin-top:14px;padding:4px 8px 0;font-size:12px;color:var(--p-list-foreground-muted)}:host ::ng-deep .mat-mdc-paginator.hide-range .mat-mdc-paginator-range-label{display:none}::ng-deep .praxis-list-paginator-select-panel.mat-mdc-select-panel{--mat-select-panel-background-color: var( --md-sys-color-surface-container, var(--mat-sys-surface-container) );background:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;background-color:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #d7dbe5) 70%,transparent);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, #000) 28%,transparent)}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option{--mat-option-label-text-color: var(--md-sys-color-on-surface, #111827);color:var(--md-sys-color-on-surface, #111827)!important}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option.mat-mdc-option-active{--mat-option-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-primary, #2f7cff) 14%, transparent );background:color-mix(in srgb,var(--md-sys-color-primary, #2f7cff) 14%,transparent)!important;color:var(--md-sys-color-on-surface, #111827)!important}.muted{color:var(--p-list-foreground-muted)}@container (max-width: 720px){.executive-inline-skin .list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.executive-inline-skin .list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--primary,.executive-inline-skin .list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.executive-inline-skin .list-item-content--row-layout .list-row-slot--meta,.executive-inline-skin .list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.executive-inline-skin .list-selection-control{padding-left:0}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.executive-inline-skin .list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.executive-inline-skin .list-item-trailing .list-item-actions{margin-inline-start:auto}.executive-inline-skin .item-expansion{margin-left:0;margin-right:0}.executive-inline-skin .list-collection-toolbar{flex-direction:column;align-items:stretch}.executive-inline-skin .list-toolbar-search,.executive-inline-skin .list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.executive-inline-skin .list-toolbar-commands{width:100%;margin-inline-start:0}.executive-inline-skin .list-toolbar-sort{flex:1 1 100%}.executive-inline-skin .list-toolbar-commands button{flex:0 0 auto}.executive-inline-skin .list-remote-error{grid-template-columns:auto minmax(0,1fr)}.executive-inline-skin .list-remote-error button{grid-column:1/-1;justify-self:stretch}}@container (max-width: 420px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}@media(max-width:640px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}.list-loading-status{display:flex;align-items:center;gap:8px;padding:12px 0;color:inherit;--mat-progress-spinner-active-indicator-color: currentColor}.list-loading-status:empty{display:none}.praxis-list-virtual-viewport,.praxis-list-bounded-viewport{display:block;width:100%;overflow-y:auto;outline:none;padding-right:4px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent) transparent}.praxis-list-virtual-viewport::-webkit-scrollbar,.praxis-list-bounded-viewport::-webkit-scrollbar{width:6px;height:6px}.praxis-list-virtual-viewport::-webkit-scrollbar-track,.praxis-list-bounded-viewport::-webkit-scrollbar-track{background:transparent}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent);border-radius:999px}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb:hover,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, #94a3b8) 72%,transparent)}.praxis-list-virtual-viewport{height:var(--p-list-viewport-height, 400px);contain:strict}.praxis-list-virtual-viewport .praxis-list-virtual-list{padding-top:0;padding-bottom:0}.list-item-menu-trigger{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--md-sys-shape-corner-full, 9999px);color:var(--p-list-foreground-muted, inherit);transition:background-color .15s ease,color .15s ease}.list-item-menu-trigger:hover{background-color:var(--p-list-item-hover-surface, rgba(0, 0, 0, .04));color:var(--p-list-foreground, inherit)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i2$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i2$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3.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: MatRadioModule }, { kind: "component", type: i4$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: i7.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i8.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i8.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i11.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4$2.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$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { kind: "component", type: ExecutiveBadgeComponent, selector: "praxis-executive-badge", inputs: ["ariaLabel", "label", "variant"] }, { kind: "component", type: ExecutiveAlertsComponent, selector: "praxis-executive-alerts", inputs: ["alerts"] }, { kind: "component", type: ExecutiveOwnerComponent, selector: "praxis-executive-owner", inputs: ["name"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }, { kind: "component", type: PraxisListMetricComponent, selector: "praxis-list-metric", inputs: ["metric"] }, { kind: "component", type: PraxisListComposeComponent, selector: "praxis-list-compose", inputs: ["compose"] }, { kind: "component", type: PraxisListRuntimeComponentComponent, selector: "praxis-list-runtime-component", inputs: ["component"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i15.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i15.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i15.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12874
13358
|
}
|
|
12875
13359
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisList, decorators: [{
|
|
12876
13360
|
type: Component,
|
|
@@ -12895,6 +13379,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
12895
13379
|
MatInputModule,
|
|
12896
13380
|
MatTooltipModule,
|
|
12897
13381
|
PraxisAiAssistantShellComponent,
|
|
13382
|
+
EmptyStateCardComponent,
|
|
12898
13383
|
ExecutiveBadgeComponent,
|
|
12899
13384
|
ExecutiveAlertsComponent,
|
|
12900
13385
|
ExecutiveOwnerComponent,
|
|
@@ -12908,7 +13393,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
12908
13393
|
ListDataService,
|
|
12909
13394
|
MatPaginatorIntl,
|
|
12910
13395
|
providePraxisListI18n(),
|
|
12911
|
-
], template: "<div class=\"list-loading-status\" role=\"status\">\n @if (loading$ | async) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\" aria-hidden=\"true\"></mat-progress-spinner>\n <span>{{ t('loading', 'Carregando itens\u2026') }}</span>\n }\n</div>\n<div\n class=\"praxis-list-root\"\n tabindex=\"-1\"\n [attr.aria-busy]=\"(loading$ | async) ? 'true' : 'false'\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.data-item-appearance]=\"config?.layout?.itemAppearance || null\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (enableCustomization) {\n <div class=\"list-assistant\">\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openConfigEditor()\"\n [matTooltip]=\"configEditorLabel()\"\n [attr.aria-label]=\"configEditorLabel()\"\n data-testid=\"praxis-list-open-config-editor\"\n >\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openAiAssistant()\"\n matTooltip=\"Copiloto semantico Praxis\"\n aria-label=\"Abrir copiloto semantico Praxis da lista\"\n data-testid=\"praxis-list-ai-assistant-trigger\"\n >\n <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"\n aiAssistantViewState.state === 'processing' ||\n aiAssistantViewState.state === 'applying'\n \"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-list-ai-assistant\"\n panelTestId=\"praxis-list-ai-assistant-panel\"\n submitTestId=\"praxis-list-ai-assistant-submit\"\n applyTestId=\"praxis-list-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n\n @if (\n config.export?.enabled ||\n (isRemoteDataMode() &&\n (config.ui?.showSort ||\n (config.ui?.showSearch && config.ui?.searchField)))\n ) {\n <div\n class=\"list-collection-toolbar\"\n role=\"group\"\n [attr.aria-label]=\"t('toolbar.label', 'Controles da lista')\"\n >\n @if (\n isRemoteDataMode() && config.ui?.showSearch && config.ui?.searchField\n ) {\n <mat-form-field\n class=\"list-toolbar-search\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{\n config.ui?.searchPlaceholder || t(\"toolbar.search\", \"Buscar\")\n }}</mat-label>\n <mat-icon matPrefix [praxisIcon]=\"'search'\"></mat-icon>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n\n <div class=\"list-toolbar-commands\">\n @if (isRemoteDataMode() && config.ui?.showSort) {\n <mat-form-field\n class=\"list-toolbar-sort\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{ t(\"toolbar.sort\", \"Ordenar por\") }}</mat-label>\n @let activeSort = activeSortValue((page$ | async)?.sort);\n <mat-select\n [value]=\"activeSort\"\n (selectionChange)=\"onSortChange($event.value)\"\n >\n @if (activeSort && !hasSortOption(activeSort)) {\n <mat-option [value]=\"activeSort\">{{ activeSort }}</mat-option>\n }\n @for (op of config.ui?.sortOptions || []; track $index) {\n <mat-option [value]=\"sortOptionValue(op)\">{{\n sortOptionLabel(op)\n }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (config.export?.enabled) {\n <button\n mat-stroked-button\n type=\"button\"\n [matMenuTriggerFor]=\"listExportMenu\"\n [attr.aria-label]=\"t('export.button', 'Exportar')\"\n [disabled]=\"exportBusy\"\n [attr.aria-busy]=\"exportBusy\"\n >\n <mat-icon [praxisIcon]=\"'download'\"></mat-icon>\n {{ t(\"export.button\", \"Exportar\") }}\n </button>\n <span class=\"cdk-visually-hidden\" aria-live=\"polite\">\n {{ exportStatusMessage }}\n </span>\n <mat-menu #listExportMenu=\"matMenu\">\n @for (format of listExportFormats(); track format) {\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"onExportAction(format)\"\n >\n <mat-icon [praxisIcon]=\"exportIcon(format)\"></mat-icon>\n {{ format.toUpperCase() }}\n </button>\n }\n </mat-menu>\n }\n </div>\n </div>\n }\n\n <!-- Skeleton while loading -->\n @if (loading$ | async) {\n @if (hasSkeleton()) {\n @if (isListVariant()) {\n <mat-list>\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <mat-list-item>\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else {\n <div class=\"cards-grid\">\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (error$ | async; as remoteError) {\n <div class=\"list-remote-error\" role=\"alert\">\n <mat-icon [praxisIcon]=\"'error_outline'\"></mat-icon>\n <div class=\"list-remote-error__copy\">\n <strong>{{\n t(\"remoteError.title\", \"N\u00E3o foi poss\u00EDvel carregar a lista\")\n }}</strong>\n <span>\n {{\n remoteError.filtered\n ? t(\n \"remoteError.filteredDescription\",\n \"Os filtros permanecem aplicados. Nenhum dado sem filtro foi exibido.\"\n )\n : t(\n \"remoteError.description\",\n \"Verifique a conex\u00E3o e tente novamente.\"\n )\n }}\n </span>\n </div>\n <button mat-stroked-button type=\"button\" (click)=\"retryRemoteData()\">\n {{ t(\"remoteError.retry\", \"Tentar novamente\") }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0 && !(error$ | async)) {\n <div\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n >\n @if (emptyStateTemplate(); as empty) {\n @if (\n simpleRichContentNodes(empty, {\n imageAlt: config.templating?.emptyState?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (empty.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"empty.value\"\n [ngClass]=\"empty.class\"\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [style.cssText]=\"\n (empty.style ? empty.style + ';' : '') +\n iconStyle(empty.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n >\n <img\n [src]=\"empty.value\"\n [alt]=\"config.templating?.emptyState?.imageAlt || ''\"\n />\n @if (empty.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(empty.badge?.color)\n ? empty.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (empty.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(empty.badge?.color, empty.badge?.variant)\n \"\n >{{ empty.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [ngClass]=\"[\n empty.class || '',\n (empty.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(empty.color, empty.variant) +\n (empty.style ? ';' + empty.style : '')\n \"\n >{{ empty.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">\n @for (\n _ of ratingRange(empty);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, empty.value)\"\n [color]=\"ratingThemeColor(empty)\"\n [style.cssText]=\"ratingIconStyle(empty)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n [innerHTML]=\"empty.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"empty\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"empty\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"empty\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">{{\n empty.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n }\n\n <ng-template\n #rowLayoutNode\n let-node\n let-slot=\"slot\"\n let-imageAlt=\"imageAlt\"\n >\n @if (\n simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt });\n as richNodes\n ) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"[\n slot === 'leading' ? 'leading-icon' : '',\n node?.class || '',\n ]\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\n slot === 'leading'\n ? leadingIconStyle(node?.color, node?.style)\n : (node?.style || '' ? node.style + ';' : '') +\n iconStyle(node?.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n >\n <img\n [src]=\"node?.value\"\n [alt]=\"node?.imageAlt || imageAlt || ''\"\n />\n @if (node?.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(node?.badge?.color)\n ? node?.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (node?.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(node?.badge?.color, node?.badge?.variant)\n \"\n >\n {{ node?.badge?.value }}\n </mat-chip>\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [ngClass]=\"[\n node?.class || '',\n (node?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(node?.color, node?.variant) +\n (node?.style ? ';' + node.style : '')\n \"\n >\n {{ node?.value }}\n </mat-chip>\n }\n @case (\"rating\") {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @for (_ of ratingRange(node); track $index; let idx = $index) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, node?.value)\"\n [color]=\"ratingThemeColor(node)\"\n [style.cssText]=\"ratingIconStyle(node)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n [innerHTML]=\"node?.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"node\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"node\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"node\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @if (\n slot === \"meta\" && config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\n }\n </ng-template>\n\n <ng-template #featureContent let-item let-feature=\"feature\">\n @if (featureTemplateNode(item, feature); as featureNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: featureNode,\n slot: 'feature',\n imageAlt: feature?.imageAlt || '',\n }\n \"\n ></ng-container>\n } @else if (featureRichContentNodes(item, feature); as featureNodes) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (feature.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"feature.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"feature.class\" [style.cssText]=\"feature.style\">\n @for (line of featureLabelLines(item, feature.expr); track $index) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, feature.expr, feature.class);\n as progress\n ) {\n <span class=\"feature-progress\" aria-hidden=\"true\">\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\n </ng-template>\n\n <ng-template\n #listRowLayout\n let-item\n let-index=\"index\"\n let-sectionKey=\"sectionKey\"\n let-clickable=\"clickable\"\n >\n <div\n class=\"list-item-content\"\n [ngClass]=\"rowLayoutItemClass(item)\"\n [attr.style]=\"rowLayoutItemStyle(item)\"\n >\n @if (clickable) {\n <button\n type=\"button\"\n class=\"list-row-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, index) : null\n \"\n (click)=\"onRowActivate(item, index, sectionKey)\"\n ></button>\n }\n @for (\n column of rowLayoutColumns();\n track rowLayoutTrackColumn($index, column)\n ) {\n <div\n [attr.data-row-slot]=\"column.slot\"\n [ngClass]=\"rowLayoutColumnClass(column)\"\n [attr.style]=\"rowLayoutColumnStyle(column)\"\n >\n @if (column.slot === \"leading\") {\n @if (rowLayoutSlot(item, column.slot); as lead) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: lead,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n } @else if (column.slot === \"trailing\") {\n @if (rowLayoutSlot(item, column.slot); as trailingNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: trailingNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"rowActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #rowActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, index)\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n } @else if (column.slot === \"actions\") {\n @if ((visibleActions(item, \"actions\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"actions\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n } @else if (column.slot === \"expand\") {\n @if (showExpandIcon(\"expand\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n } @else if (rowLayoutSlot(item, column.slot); as slotNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: slotNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- List variant -->\n @if (isListVariant()) {\n <!-- Selection and row actions share one neutral list shell so every\n interactive affordance remains a sibling keyboard target. -->\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n\n <!-- Unified list surface -->\n <ng-template #readList>\n @if (isVirtualScrollEnabled()) {\n <cdk-virtual-scroll-viewport\n class=\"praxis-list-virtual-viewport\"\n [itemSize]=\"virtualScrollItemSize()\"\n [minBufferPx]=\"virtualScrollMinBufferPx()\"\n [maxBufferPx]=\"virtualScrollMaxBufferPx()\"\n [style.height]=\"virtualScrollViewportHeight()\"\n >\n <mat-list\n class=\"praxis-list-virtual-list\"\n role=\"list\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n <mat-list-item\n *cdkVirtualFor=\"\n let item of virtualScrollItems(sections$ | async, items$ | async);\n let i = index;\n trackBy: trackByVirtualItem\n \"\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n </mat-list>\n </cdk-virtual-scroll-viewport>\n } @else {\n <mat-list\n role=\"list\"\n [class.praxis-list-bounded-viewport]=\"hasBoundedScrollViewport()\"\n [style.max-height]=\"hasBoundedScrollViewport() ? virtualScrollViewportHeight() : null\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section);\n let sidx = $index\n ) {\n @if (section.key) {\n <div class=\"section-header mat-subheader\">\n @if (sectionHeaderTemplate(section.key); as sh) {\n @if (\n simpleRichContentNodes(sh, {\n imageAlt:\n config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (sh.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"sh.value\"\n [ngClass]=\"sh.class\"\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') +\n iconStyle(sh.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n >\n <img\n [src]=\"sh.value\"\n [alt]=\"\n config.templating?.sectionHeader?.imageAlt || ''\n \"\n />\n @if (sh.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(sh.badge?.color)\n ? sh.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (sh.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(sh.badge?.color, sh.badge?.variant)\n \"\n >{{ sh.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [ngClass]=\"[\n sh.class || '',\n (sh.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(sh.color, sh.variant) +\n (sh.style ? ';' + sh.style : '')\n \"\n >{{ sh.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">\n @for (\n _ of ratingRange(sh);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, sh.value)\"\n [color]=\"ratingThemeColor(sh)\"\n [style.cssText]=\"ratingIconStyle(sh)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n [innerHTML]=\"sh.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"sh\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"sh\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"sh\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">{{\n sh.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n @for (\n item of section.items;\n track trackByItem($index, item);\n let i = $index\n ) {\n <mat-list-item\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider\n role=\"presentation\"\n aria-hidden=\"true\"\n ></mat-divider>\n }\n }\n }\n </mat-list>\n }\n </ng-template>\n\n <ng-template #listItemBody let-item let-i=\"index\" let-sectionKey=\"sectionKey\">\n <div\n class=\"list-row-shell\"\n [class.list-row-shell--selectable]=\"isSelectionEnabled()\"\n [class.list-row-shell--with-control]=\"shouldShowSelectionControl()\"\n [class.list-row-shell--selected]=\"isItemSelected(item)\"\n [class.list-row-shell--expanded]=\"isExpandable() && isExpanded(item, i)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: sectionKey,\n clickable: true,\n }\n \"\n ></ng-container>\n } @else {\n <div\n class=\"list-item-content\"\n [ngClass]=\"itemRuleClass(item)\"\n [attr.style]=\"itemRuleStyle(item)\"\n >\n <button\n type=\"button\"\n class=\"list-item-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, i) : null\n \"\n (click)=\"\n onRowActivate(item, i, sectionKey)\n \"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt:\n config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"\n config.templating?.leading?.imageAlt ||\n ''\n \"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(lead.color, lead.variant)\n \"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(item)?.class\"\n [style.cssText]=\"primary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(primary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(item)\"\n ></praxis-list-metric>\n } @else if (primary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(item)\"\n ></praxis-list-compose>\n } @else if (primary(item)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(item)\"\n ></praxis-list-runtime-component>\n } @else if (primary(item)?.type === \"html\") {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(item)?.class\"\n [style.cssText]=\"secondary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(secondary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (\n item.segmentVariant &&\n item.segmentLabel &&\n item.accountType &&\n item.since\n ) {\n <!-- Component-based rendering for executive items -->\n <span class=\"exec-subline\">\n <praxis-executive-badge\n [variant]=\"item.segmentVariant\"\n [label]=\"item.segmentLabel\"\n ></praxis-executive-badge>\n <span class=\"exec-subcopy\">{{\n item.accountType\n }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\"\n >Desde {{ item.since }}</span\n >\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span\n [innerHTML]=\"secondary(item)?.value\"\n ></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\n } @else if (secondary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(item)\"\n ></praxis-list-compose>\n } @else if (\n secondary(item)?.type === \"component\"\n ) {\n <praxis-list-runtime-component\n [component]=\"secondary(item)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (meta(item); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: item, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n </div>\n </button>\n <div class=\"list-item-trailing\">\n @if (meta(item); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, { slot: \"meta\" });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(m.color, m.variant)\n \"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"m.value\"\n [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon\n [praxisIcon]=\"mpi2\"\n ></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(item); as tr) {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt:\n config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr.color, tr.variant)\n \"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt ||\n ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n @if (\n item.alertsData !== undefined &&\n item.ownerName\n ) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts\n [alerts]=\"item.alertsData\"\n ></praxis-executive-alerts>\n <praxis-executive-owner\n [name]=\"item.ownerName\"\n ></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, i)\n ? 'expand_less'\n : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon()\n ? isExpanded(item, i)\n : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n action.icon || 'more_horiz'\n \"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, i)\"\n [style.cssText]=\"\n actionIconStyle(action.color)\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'stroked')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'raised')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant ||\n action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'flat')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"itemActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #itemActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, i)\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (shouldShowSelectionControl()) {\n <div class=\"list-selection-control\">\n @if (config.selection?.mode === \"multiple\") {\n <mat-checkbox\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, $event.checked)\"\n ></mat-checkbox>\n } @else {\n <mat-radio-button\n [name]=\"selectionControlName()\"\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, true)\"\n ></mat-radio-button>\n }\n </div>\n }\n </div>\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\n [ngClass]=\"expansionRenderingClasses()\"\n [style]=\"expansionRenderingStyle()\"\n [id]=\"expandRegionId(item, i)\"\n role=\"region\"\n [attr.aria-label]=\"expansionRegionAriaLabel(item)\"\n >\n <div class=\"item-expansion-grid\">\n @for (\n expansionSection of expansionSections(item);\n track expansionSection.id\n ) {\n <section\n class=\"expansion-section\"\n [attr.data-section-type]=\"expansionSection.type\"\n >\n @if (expansionSection.title) {\n <div class=\"expansion-section-title\">\n {{ expansionSection.title }}\n </div>\n }\n @if (\n expansionSectionHasContent(\n item,\n expansionSection,\n i\n )\n ) {\n @switch (expansionSection.type) {\n @case (\"chip-list\") {\n <div class=\"expansion-chip-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <mat-chip class=\"expansion-chip\">{{\n expansionItemLabel(expansionEntry)\n }}</mat-chip>\n }\n </div>\n }\n @case (\"timeline\") {\n <div class=\"expansion-timeline\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-timeline-item\">\n <div class=\"expansion-timeline-title\">\n {{\n expansionTimelineTitle(expansionEntry)\n }}\n </div>\n @if (\n expansionTimelineMeta(expansionEntry)\n ) {\n <div class=\"expansion-timeline-meta\">\n {{\n expansionTimelineMeta(\n expansionEntry\n )\n }}\n </div>\n }\n @if (\n expansionTimelineDescription(\n expansionEntry\n )\n ) {\n <div\n class=\"expansion-timeline-description\"\n >\n {{\n expansionTimelineDescription(\n expansionEntry\n )\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n @case (\"key-value\") {\n <dl class=\"expansion-key-value\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-key-value-row\">\n @if (\n expansionKeyValueKey(expansionEntry)\n ) {\n <dt>\n {{\n expansionKeyValueKey(expansionEntry)\n }}\n </dt>\n }\n <dd>\n {{\n expansionKeyValueValue(expansionEntry)\n }}\n </dd>\n </div>\n }\n </dl>\n }\n @case (\"rich-content\") {\n @if (\n expansionRichContentDocument(\n item,\n expansionSection,\n i\n );\n as richExpansionDocument\n ) {\n <praxis-rich-content\n [document]=\"richExpansionDocument\"\n [context]=\"\n expansionRichContentContext(\n item,\n expansionSection,\n i\n )\n \"\n [hostCapabilities]=\"\n expansionRichContentHostCapabilities(\n item,\n expansionSection,\n i\n )\n \"\n rootClassName=\"praxis-list-expansion-rich-content\"\n ></praxis-rich-content>\n }\n }\n @default {\n <div class=\"expansion-info-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-info-item\">\n <div class=\"expansion-info-title\">\n {{ expansionInfoTitle(expansionEntry) }}\n </div>\n @if (expansionInfoValue(expansionEntry)) {\n <div class=\"expansion-info-value\">\n {{\n expansionInfoValue(expansionEntry)\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n }\n } @else {\n <div class=\"expansion-empty\">\n {{\n expansionSection.emptyLabel ||\n \"Sem dados dispon\u00EDveis\"\n }}\n </div>\n }\n </section>\n }\n </div>\n </div>\n }\n </ng-template>\n } @else if (isTilesVariant()) {\n <ng-container *ngTemplateOutlet=\"tilesVariant\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"cardsVariant\"></ng-container>\n }\n\n <!-- Cards variant -->\n <ng-template #cardsVariant>\n <div class=\"cards-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-card\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"list-item-content card-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (detail of detailSlots; track detail.slot) {\n <div\n class=\"card-detail\"\n [ngClass]=\"'card-detail--' + detail.slot\"\n >\n <span class=\"card-detail__label\">{{\n detail.label\n }}</span>\n <span class=\"card-detail__value\">\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: detail.node,\n slot: detail.slot,\n imageAlt: rowLayoutImageAlt(detail.slot),\n }\n \"\n ></ng-container>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n <div class=\"list-item-trailing\">\n @if (meta(it); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (config.templating?.metaPrefixIcon; as mpi2) {\n <mat-icon [praxisIcon]=\"mpi2\"></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"status-overlay\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n } @else {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt || ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Tiles variant -->\n <ng-template #tilesVariant>\n <div class=\"tiles-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-tile\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"tile-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"image\") {\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\n \"\n ></mat-icon>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n }\n </div>\n\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"tile-status\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n }\n }\n\n <div class=\"tile-body\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n\n @if (meta(it); as m) {\n <div\n class=\"tile-meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"m\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ m.value }}</span>\n }\n }\n }\n </div>\n }\n\n @if (featuresVisible()) {\n <div class=\"tiles-features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n\n @if (trailing(it); as tr2) {\n @if (\n !(\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr2?.type === \"chip\" || tr2?.type === \"icon\")\n )\n ) {\n <div\n class=\"tile-trailing\"\n [ngClass]=\"tr2.class\"\n [style.cssText]=\"tr2.style\"\n >\n @if (\n simpleRichContentNodes(tr2, {\n imageAlt: tr2.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [ngClass]=\"\n (tr2.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr2.color, tr2.variant)\n \"\n >{{ tr2.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr2.value\"\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr2.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"tr2.value\"\n [alt]=\"tr2.imageAlt || ''\"\n /></span>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr2);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr2.value)\"\n [color]=\"ratingThemeColor(tr2)\"\n [style.cssText]=\"ratingIconStyle(tr2)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr2.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr2\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr2\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr2\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr2.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n\n @if ((visibleActions(it, \"trailing\") || []).length) {\n <div\n class=\"tile-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Remote pagination stays attached to the collection footer. -->\n @if (isRemoteDataMode() && !(error$ | async)) {\n @if (page$ | async; as ps) {\n @if (total$ | async; as total) {\n @if (config.ui?.showRange === false) {\n <div class=\"list-paginator-total\" aria-live=\"polite\">\n {{ remoteTotalLabel(total) }}\n </div>\n }\n <mat-paginator\n [length]=\"total || 0\"\n [pageIndex]=\"ps.pageNumber || 0\"\n [pageSize]=\"ps.pageSize || config.layout?.pageSize || 10\"\n [pageSizeOptions]=\"listPageSizeOptions()\"\n [selectConfig]=\"paginatorSelectConfig\"\n [showFirstLastButtons]=\"true\"\n [class.hide-range]=\"config.ui?.showRange === false\"\n (page)=\"onPageChange($event)\"\n >\n </mat-paginator>\n }\n }\n }\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block}.praxis-list-root{container-type:inline-size;--p-list-radius: var(--md-sys-shape-corner-medium, 16px);--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-blur: 10px;--p-list-surface: var(--md-sys-color-surface-container);--p-list-surface-low: var(--md-sys-color-surface);--p-list-surface-high: var( --md-sys-color-surface-container-high, var(--md-sys-color-surface-container) );--p-list-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-accent: var(--md-sys-color-primary);--p-list-accent-weak: var(--md-sys-color-primary-container);--p-list-item-surface: var( --md-sys-color-surface-container-low, var(--md-sys-color-surface) );--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--p-list-item-hover-surface: var(--md-sys-color-surface-container-low);--p-list-item-active-surface: var(--md-sys-color-surface-container);--p-list-item-selected-surface: var(--md-sys-color-surface-container);--p-list-grad-from: var(--md-sys-color-primary-container);--p-list-grad-to: var(--md-sys-color-tertiary-container);--p-list-grad-angle: 135deg;--p-list-grad-foreground: var( --md-sys-color-on-primary-container, var(--md-sys-color-on-surface) );--p-list-grad-foreground-muted: color-mix( in srgb, var(--p-list-grad-foreground) 76%, transparent );--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--p-list-trailing-max-width: 320px;--p-list-item-gap: 10px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 10px;--p-list-item-stack-gap: 0px;--p-list-meta-size: .875rem;--p-list-meta-weight: 500;--p-list-chip-height: 22px;--p-list-chip-font-size: 12px;--p-list-trailing-padding-right: 8px;--p-list-action-button-height: 32px;--p-list-tile-minW: 240px;--p-list-tile-gap: 12px;--p-list-tile-padding: 12px;--p-list-tile-radius: 12px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;--p-list-tile-hover-overlay: .04;--p-list-tile-press-overlay: .08;--p-list-tile-press-scale: .99}.list-assistant{display:flex;justify-content:flex-end;gap:8px;padding:4px 4px 8px}.action-loading{opacity:.65}.action-spinner{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}.action-loading .mat-mdc-button-touch-target,.action-loading .mdc-button__label{opacity:.7}.skin-elevated,.skin-outline,.skin-flat,.skin-neumorphism{--p-list-item-surface: var( --mdc-elevated-card-container-color, var(--p-list-surface) );--p-list-item-border: var(--p-list-border)}.skin-elevated .item-card,.skin-outline .item-card,.skin-flat .item-card,.skin-neumorphism .item-card{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:var(--p-list-radius);box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .item-tile,.skin-outline .item-tile,.skin-flat .item-tile,.skin-neumorphism .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .mat-mdc-list-item .list-item-content,.skin-outline .mat-mdc-list-item .list-item-content,.skin-flat .mat-mdc-list-item .list-item-content,.skin-neumorphism .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * .75);box-shadow:var(--p-list-shadow);border:var(--p-list-item-border);color:var(--p-list-foreground)}.skin-outline{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline)}.skin-flat{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline-variant)}.skin-neumorphism{--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-radius: 1.25rem}.skin-pill-soft .item-card,.skin-pill-soft .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border)}.skin-pill-soft .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border);color:var(--p-list-foreground)}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted);--p-list-item-hover-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-active-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-selected-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) )}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-gradient-tile .tile-media{background:color-mix(in srgb,var(--md-sys-color-surface) 74%,transparent);border-color:color-mix(in srgb,var(--p-list-foreground) 22%,transparent)}.skin-gradient-tile .tile-media mat-icon,.skin-gradient-tile .tile-meta,.skin-gradient-tile .tile-trailing,.skin-gradient-tile .feature,.skin-gradient-tile .secondary,.skin-gradient-tile .meta{color:var(--p-list-foreground-muted)}.skin-gradient-tile .tile-status,.skin-gradient-tile [data-rich-node-type=badge] .prx-rich-badge{color:var(--md-sys-color-on-secondary-container, var(--p-list-foreground));background:var(--md-sys-color-secondary-container, rgba(255, 255, 255, .72))}.skin-gradient-tile .mat-mdc-list-item .list-item-content{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-glass .item-card,.skin-glass .item-tile{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.skin-glass .mat-mdc-list-item .list-item-content{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.density-compact .mat-mdc-list-item,.density-compact .item-card{--p-list-item-padding-y: 6px;--p-list-item-padding-x: 10px;--p-list-item-gap: 8px}.density-comfortable .mat-mdc-list-item,.density-comfortable .item-card{--p-list-item-padding-y: 8px;--p-list-item-padding-x: 12px;--p-list-item-gap: 10px}.praxis-list-root.lines-3 .mat-mdc-list-item{min-height:68px}.density-compact{--p-list-tile-gap: 10px;--p-list-tile-padding: 10px;--p-list-tile-minW: 188px}.density-comfortable{--p-list-tile-gap: 12px;--p-list-tile-padding: 12px}.item-spacing-none{--p-list-item-stack-gap: 0px}.item-spacing-tight{--p-list-item-stack-gap: 4px;--p-list-tile-gap: 10px}.item-spacing-default{--p-list-item-stack-gap: 6px;--p-list-tile-gap: 12px}.item-spacing-relaxed{--p-list-item-stack-gap: 14px;--p-list-tile-gap: 20px}.list-item-content{box-sizing:border-box;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),min(34vw,var(--p-list-trailing-max-width)));align-items:center;gap:var(--p-list-item-gap);padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x);width:100%;min-width:0;border-radius:calc(var(--p-list-radius) * .75);overflow:visible}.list-item-content--row-layout{--p-list-row-template-columns: var(--p-list-leading-width) minmax(0, 1fr) minmax(var(--p-list-trailing-min-width), max-content);--p-list-row-gap: var(--p-list-item-gap);--p-list-row-align-items: center;grid-template-columns:var(--p-list-row-template-columns);gap:var(--p-list-row-gap);align-items:var(--p-list-row-align-items);position:relative}.list-row-main-action{position:absolute;inset:0;z-index:1;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer}.list-row-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{position:relative;z-index:0;min-width:0;height:100%;align-self:stretch;display:flex;align-items:var(--p-list-row-slot-align-items, center);gap:8px}.list-item-content--row-layout :is(.list-row-slot--actions,.list-row-slot--expand,.list-row-slot--trailing){z-index:2}.list-item-content--row-layout .list-row-slot>praxis-rich-content,.list-item-content--row-layout .list-row-slot>praxis-list-metric,.list-item-content--row-layout .list-row-slot>praxis-list-compose,.list-item-content--row-layout .list-row-slot>praxis-list-runtime-component{min-width:0}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary,.list-row-slot--identity{min-width:0}.list-row-slot--identity>praxis-list-compose,.list-row-slot--primary>praxis-list-compose,.list-row-slot--secondary>praxis-list-compose{width:100%}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:nowrap;justify-content:flex-end;gap:8px}.list-row-slot .primary,.list-row-slot .secondary,.list-row-slot .meta,.list-row-slot .trailing{min-width:0}.list-item-main-action{grid-column:1/3;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr);align-items:center;gap:var(--p-list-item-gap);min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.list-item-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:12px}.list-item-leading{display:flex;align-items:center;justify-content:center;min-width:0;min-height:100%}.list-item-leading>praxis-rich-content,.list-row-slot--leading>praxis-rich-content{min-width:0;max-width:100%}:host ::ng-deep .list-item-leading [data-rich-node-type=icon],:host ::ng-deep .list-row-slot--leading [data-rich-node-type=icon]{width:36px;height:36px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 14%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 28%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary, #06b6d4));box-sizing:border-box;flex-shrink:0}.leading-placeholder{width:24px;height:24px;display:inline-block}.list-item-text{min-width:0;display:grid;align-content:center;gap:2px}.list-item-trailing{box-sizing:border-box;min-width:0;width:100%;max-width:var(--p-list-trailing-max-width);display:flex;flex-wrap:nowrap;align-self:center;align-content:center;align-items:center;justify-content:end;gap:8px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-trailing>*{align-self:center}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{width:max-content;justify-self:end;align-self:center;display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap;max-width:100%;min-height:var(--p-list-action-button-height)}.list-item-actions .mat-mdc-button-base{min-height:var(--p-list-action-button-height);height:var(--p-list-action-button-height);display:inline-flex;align-items:center}.expand-toggle{color:var(--p-list-foreground-muted)}.mat-mdc-list-item .list-item-content{background:var(--p-list-item-surface);border:var(--p-list-item-border);transition:background .15s ease,box-shadow .15s ease,transform .15s ease}.mat-mdc-list-item{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-item.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-three-lines,.mat-mdc-list-item-single-line,.mat-mdc-list-item-two-line,.mat-mdc-list-item-three-line{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item{min-height:40px}.density-comfortable .mat-mdc-list-item{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text{display:block!important;width:100%!important;height:auto!important;padding:0!important;margin:0!important;overflow:visible!important;box-sizing:border-box}.mat-mdc-list-item{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list mat-list-item:not(:last-child),.praxis-list-root .mat-mdc-list-item:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:var(--p-list-radius, 12px);box-shadow:var(--p-list-shadow, 0 1px 3px rgba(0, 0, 0, .2))}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item:hover .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item:hover .list-item-content{border-color:var(--md-sys-color-primary, #6750a4);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0, 0, 0, .25))}.praxis-list-root[data-item-appearance=capsule] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-capsule .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:9999px;box-shadow:var(--p-list-shadow, none)}.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-item-content,.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-row-shell--selectable,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-row-shell--selectable{background:transparent;border:none;box-shadow:none;border-radius:0}.mat-mdc-list-item:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-shell{width:100%;min-width:0}.list-row-shell--selectable{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;border-radius:calc(var(--p-list-radius) * .75);background:var(--p-list-item-surface);border:var(--p-list-item-border);color:var(--p-list-foreground);overflow:hidden;transition:background .15s ease,box-shadow .15s ease,border-color .15s ease}.list-row-shell--selectable.list-row-shell--with-control{grid-template-columns:minmax(0,1fr) auto}.list-selection-control{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:center;padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x) var(--p-list-item-padding-y) 0}.list-selection-control mat-radio-button{--mat-radio-selected-icon-color: var(--p-list-foreground);--mat-radio-selected-hover-icon-color: var(--p-list-foreground);--mat-radio-selected-focus-icon-color: var(--p-list-foreground);--mat-radio-selected-pressed-icon-color: var(--p-list-foreground);--mat-radio-checked-ripple-color: var(--p-list-foreground)}.praxis-list-root .mat-mdc-list-item .list-row-shell--selectable .list-item-content{background:transparent;border:0;border-radius:0;box-shadow:none}.mat-mdc-list-item:hover .list-row-shell--selectable{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-row-shell--selectable{background:var(--p-list-item-active-surface)}.list-row-shell--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.skin-elevated .list-row-shell--selectable,.skin-outline .list-row-shell--selectable,.skin-flat .list-row-shell--selectable,.skin-neumorphism .list-row-shell--selectable{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-item-border);box-shadow:var(--p-list-shadow)}.skin-pill-soft .list-row-shell--selectable{border-radius:calc(var(--p-list-radius) * 1.3);background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-border);box-shadow:var(--md-sys-elevation-level1)}.skin-gradient-tile .list-row-shell--selectable{border-radius:var(--p-list-radius);background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));color:var(--p-list-foreground)}.skin-glass .list-row-shell--selectable{border-radius:var(--p-list-radius);background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.executive-inline-skin{--p-list-leading-width: 56px;--p-list-trailing-min-width: 232px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 8px;--p-list-item-gap: 10px;--p-list-surface: #f8fafb;--p-list-surface-low: #ffffff;--p-list-item-surface: #ffffff;--p-list-item-hover-surface: #f7fafc;--p-list-item-active-surface: #eef4f8;--p-list-item-selected-surface: #eef4f8;--p-list-foreground: #17324d;--p-list-foreground-muted: #72849a}.executive-inline-skin .list-item-content--row-layout.exec-row-layout{min-height:72px;padding:12px 20px;background:linear-gradient(180deg,#fff,#fbfcfd)!important;border:1px solid #dce5ec!important;border-radius:18px;box-shadow:0 1px 2px #0f223a08,0 4px 14px #0f223a08!important;color:#17324d!important}.executive-inline-skin .mat-mdc-list-item:hover .list-item-content--row-layout.exec-row-layout{background:linear-gradient(180deg,#fff,#f7fafc)!important}.executive-inline-skin .list-item-content--row-layout.exec-row-layout+.item-expansion{margin-left:10px;margin-right:10px}.executive-inline-skin .list-item-content--row-layout.exec-row-layout .list-row-slot{min-height:34px}.executive-inline-skin .list-row-slot--leading{justify-content:center}.executive-inline-skin .list-row-slot--identity{align-items:center;padding-right:4px}.executive-inline-skin .list-row-slot--balance,.executive-inline-skin .list-row-slot--limit,.executive-inline-skin .list-row-slot--risk,.executive-inline-skin .list-row-slot--alerts{justify-content:center;padding-inline:2px}.executive-inline-skin .list-row-slot--owner{justify-content:flex-start;padding-left:0}.executive-inline-skin .list-row-slot--actions{justify-content:flex-end;padding-left:0}.executive-inline-skin .list-row-slot--expand{justify-content:center}.executive-inline-skin .docs-expansion-leading{width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center;border-radius:15px;background:linear-gradient(180deg,#edf4f9,#e6eef5);color:#1b5f86;font-size:1rem;font-weight:800;letter-spacing:.02em;box-shadow:0 1px 3px #1b5f861f;border:1px solid #dbe7f0}.executive-inline-skin .exec-balance-metric,.executive-inline-skin .exec-limit-metric,.executive-inline-skin .exec-risk-metric{min-width:0}.executive-inline-skin .exec-balance-metric .p-list-metric,.executive-inline-skin .exec-limit-metric .p-list-metric,.executive-inline-skin .exec-risk-metric .p-list-metric{gap:5px}.executive-inline-skin .exec-balance-metric .p-list-metric__label,.executive-inline-skin .exec-limit-metric .p-list-metric__label,.executive-inline-skin .exec-risk-metric .p-list-metric__label{font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#8090a1}.executive-inline-skin .exec-balance-metric .p-list-metric__value,.executive-inline-skin .exec-limit-metric .p-list-metric__value{font-size:.96rem;font-weight:800;letter-spacing:-.02em;color:#0d1f34;line-height:1.05}.executive-inline-skin .exec-limit-metric .p-list-metric__caption{font-size:.66rem;font-weight:700;color:#8090a1}.executive-inline-skin .exec-limit-metric .p-list-metric__progress{width:68px;justify-self:center;height:3px}.executive-inline-skin .exec-risk-metric{min-width:84px}.executive-inline-skin .exec-risk-metric .p-list-metric{justify-items:center}.executive-inline-skin .exec-risk-metric .p-list-metric__main{gap:6px}.executive-inline-skin .exec-risk-metric .p-list-metric__value{font-size:1.02rem;font-weight:800;letter-spacing:-.024em;line-height:1}.executive-inline-skin .exec-risk-metric .p-list-metric__progress{width:56px;justify-self:center;height:3px}.executive-inline-skin .exec-risk-metric .p-list-metric__caption{font-size:.7rem;font-weight:700;line-height:1.1}.executive-inline-skin .exec-risk-metric .p-list-metric__caption--below-progress{justify-self:center;margin-top:-1px}.executive-inline-skin .exec-risk-metric .p-list-metric__icon mat-icon{width:15px;height:15px;font-size:15px}.executive-inline-skin .list-item-actions{gap:6px;flex-wrap:nowrap}.executive-inline-skin .list-row-slot--actions .list-item-actions{justify-content:flex-end}.executive-inline-skin .list-item-actions button,.executive-inline-skin .expand-toggle{width:30px;height:30px;min-width:30px;border-radius:12px;color:#6d7f93!important}.executive-inline-skin .list-item-actions button mat-icon,.executive-inline-skin .expand-toggle mat-icon{width:18px;height:18px;font-size:18px}.executive-inline-skin .item-expansion{position:relative;margin-top:-10px;padding:22px 26px;background:linear-gradient(180deg,#fcfdfe,#f5f8fb);border-color:#e4eaf0;border-radius:0 0 22px 22px;box-shadow:inset 0 1px #ffffffdb}.lead-image{position:relative;width:96px;height:72px;border-radius:12px;overflow:hidden}.lead-image img{width:100%;height:100%;object-fit:cover;display:block}.lead-image .lead-badge{position:absolute;left:8px;bottom:8px}.inline-image{position:relative;width:20px;height:20px;border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.inline-image img{width:100%;height:100%;object-fit:cover;display:block}.inline-image .inline-badge{position:absolute;left:2px;bottom:2px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-media .list-item-content{gap:16px}.model-media .item-card{--p-list-leading-width: 136px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.model-hotel .item-card{--p-list-leading-width: 160px}.primary,.secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.primary{-webkit-line-clamp:1;font-weight:600;color:var(--p-list-foreground)}.secondary{-webkit-line-clamp:1;color:var(--p-list-foreground-muted)}.lines-3 .tertiary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-tile .primary{-webkit-line-clamp:2;font-size:.95rem;line-height:1.25rem}.item-tile .secondary{-webkit-line-clamp:2;font-size:.8rem;line-height:1.1rem}.tertiary{color:var(--p-list-foreground-muted)}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:inherit}.feature{display:inline-flex;align-items:center;gap:6px}.feature-line{display:block}.feature-progress{display:block;width:88px;height:4px;margin-top:6px;border-radius:999px;background:#dbe5eb;overflow:hidden}.feature-progress__value{display:block;height:100%;border-radius:inherit;background:#2f9b69}.meta{color:var(--p-list-foreground);font-size:var(--p-list-meta-size);font-weight:var(--p-list-meta-weight);font-variant-numeric:tabular-nums;max-width:100%;min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta>span,.meta praxis-rich-content{min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta .mat-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;line-height:1;vertical-align:middle}.trailing{color:var(--p-list-foreground-muted);margin-left:0;max-width:100%;min-width:0;display:inline-flex;justify-content:flex-end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trailing praxis-rich-content{min-width:0}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:2px 10px;border-radius:999px;font-size:.72rem;font-weight:600;letter-spacing:.02em;border:1px solid var(--p-list-chip-border-color, transparent);background:var(--p-list-chip-background, var(--md-sys-color-primary-container, #e8def8));color:var(--p-list-chip-color, var(--md-sys-color-on-primary-container, #21005d));line-height:18px}.section-header{display:block;font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.section-header praxis-rich-content{display:block;width:100%}.section-header--setup{margin:8px 12px 12px;padding:14px 16px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:color-mix(in srgb,var(--p-list-surface) 92%,var(--md-sys-color-primary) 8%);color:var(--p-list-foreground);font-weight:500}.praxis-list-root mat-list{display:block;padding-bottom:12px}.praxis-list-root .mat-divider{margin-left:var(--p-list-item-padding-x);margin-right:var(--p-list-item-padding-x)}.item-expansion{margin:0 var(--p-list-item-padding-x) var(--p-list-item-stack-gap);padding:var(--p-list-expansion-padding, 14px 16px);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.praxis-list-root[data-item-appearance=card] .list-row-shell--expanded .list-item-content,.praxis-list-root.item-appearance-card .list-row-shell--expanded .list-item-content{border-bottom-left-radius:0;border-bottom-right-radius:0}.praxis-list-root[data-item-appearance=card] .item-expansion--attached,.praxis-list-root.item-appearance-card .item-expansion--attached{margin:0;border-top:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--p-list-radius, 12px);border-bottom-right-radius:var(--p-list-radius, 12px);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--p-list-surface)) 82%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 65%,transparent)}.skin-glass .item-expansion--attached{backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.item-expansion--detached,.item-expansion--modal{margin-top:var(--p-list-item-stack-gap);background:var(--md-sys-color-surface-container, var(--p-list-surface));box-shadow:var(--md-sys-elevation-level1)}.item-expansion--modal{border-color:var(--md-sys-color-outline);box-shadow:var(--md-sys-elevation-level3)}.item-expansion-grid{display:grid;grid-template-columns:var(--p-list-expansion-columns, repeat(auto-fit, minmax(220px, 1fr)));gap:var(--p-list-expansion-gap, 16px)}.expansion-section{min-width:0;display:grid;gap:10px;align-content:start}.expansion-section-title{font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-info-list,.expansion-timeline,.expansion-key-value{display:grid;gap:10px}.expansion-info-item,.expansion-timeline-item{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--p-list-item-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent 28%)}.expansion-info-title,.expansion-timeline-title{font-size:.92rem;font-weight:600;color:var(--p-list-foreground)}.expansion-info-value,.expansion-timeline-meta,.expansion-timeline-description,.expansion-empty{font-size:.82rem;line-height:1.45;color:var(--p-list-foreground-muted)}.expansion-chip-list{display:flex;flex-wrap:wrap;gap:8px}.expansion-chip{background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant)}.expansion-key-value{margin:0;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 16px}.expansion-key-value-row{display:grid;gap:2px;padding:6px 10px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest, rgba(255, 255, 255, .04)) 45%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 45%,transparent)}.expansion-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.68rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.85rem;font-weight:600;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, max(300px, var(--p-list-tile-minW)))), 1fr)));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, var(--p-list-tile-minW))), 1fr)));gap:var(--p-list-tile-gap)}.item-tile{position:relative;display:flex;flex-direction:column;gap:10px;padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);background:var(--p-list-surface);border:var(--p-list-border);color:var(--p-list-foreground);cursor:pointer;min-height:160px;transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out}.item-tile:hover{box-shadow:var(--md-sys-elevation-level2);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-tile:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.tile-main-action{display:flex;flex:1;min-width:0;flex-direction:column;gap:10px;color:inherit;cursor:pointer}.tile-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant);display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover;display:block}.tile-media mat-icon{font-size:28px;height:28px;width:28px;color:var(--p-list-foreground-muted)}.tile-body{display:grid;gap:6px;min-width:0}.tile-meta{display:inline-flex;align-items:center;gap:6px;font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile-trailing{font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap}.tiles-features{display:flex;flex-wrap:wrap;gap:8px;color:inherit}.tile-status{position:absolute;top:10px;right:10px}.tile-actions{position:absolute;top:8px;left:8px;display:flex;gap:4px;opacity:0;pointer-events:none;transform:translateY(-2px);transition:opacity .16s ease-out,transform .16s ease-out}.item-tile:hover .tile-actions,.item-tile:focus-within .tile-actions{opacity:1;pointer-events:auto;transform:translateY(0)}@media(hover:none){.tile-actions{opacity:1;pointer-events:auto;transform:none}}@media(max-width:600px){.tiles-grid,.cards-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}@media(prefers-reduced-motion:reduce){.item-tile,.tile-actions{transition:none}.item-tile:active{transform:none}.item-card{transition:none}.item-card:active{transform:none}}.item-card{padding:max(var(--p-list-tile-padding),16px);display:flex;flex-direction:column;gap:var(--p-list-item-gap);min-height:var(--p-list-card-minH, 220px);position:relative;cursor:pointer;background:var(--p-list-surface);border:var(--p-list-border);border-radius:var(--p-list-tile-radius);box-shadow:var(--p-list-shadow);transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out;--p-list-leading-width: 96px;--p-list-trailing-min-width: 0px}.density-compact .item-card{min-height:var(--p-list-card-minH, 148px)}.pdx-list-item--primary{--p-list-item-rule-tone: var(--md-sys-color-primary, #06b6d4);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 52%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--success{--p-list-item-rule-tone: var(--p-color-success, #10b981);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 48%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--warning{--p-list-item-rule-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) );border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 54%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 10%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--danger{--p-list-item-rule-tone: var(--md-sys-color-error, #ef4444);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 56%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 11%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--muted{opacity:.78;border-style:dashed!important;background:color-mix(in srgb,var(--md-sys-color-surface-variant) 34%,var(--p-list-surface))!important}.pdx-list-item--neutral{border-color:var(--md-sys-color-outline-variant)!important;background:var(--p-list-surface)!important}.card-main-action{display:block;width:100%;min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.card-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.item-card .list-item-content{display:block;padding:0;min-width:0;overflow:hidden}.item-card .list-item-leading{position:absolute;top:18px;left:18px;min-height:0;z-index:1}.item-card .leading-placeholder{width:36px;height:36px}.item-card .leading-icon.mat-icon,.item-card .list-item-leading>mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent));color:var(--md-sys-color-primary)}.item-card .list-item-text{display:grid;gap:9px;padding-left:50px;width:100%;min-width:0;box-sizing:border-box}.item-card .primary{padding-right:min(50%,160px);font-size:1rem;font-weight:800;letter-spacing:-.01em;line-height:1.18;min-width:0;overflow-wrap:anywhere}.item-card .secondary{color:var(--p-list-foreground-muted);font-weight:600;line-height:1.35;min-width:0;overflow-wrap:anywhere}.item-card .features{display:flex;flex-direction:column;gap:8px;margin-top:2px}.item-card .feature{display:inline-flex;align-items:start;gap:8px;min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .feature mat-icon{margin-top:1px;color:var(--p-list-foreground-muted);opacity:.86}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width);grid-column:1/-1;align-items:stretch;padding-right:0}.card-detail-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px;margin-top:16px}.card-detail{min-width:0;padding:11px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 22%,transparent),color-mix(in srgb,var(--p-list-surface) 92%,transparent));box-shadow:inset 0 1px #ffffff14}.card-detail__label{display:block;margin-bottom:3px;color:var(--p-list-foreground-muted);font-size:.68rem;font-weight:700;letter-spacing:.08em;line-height:1.1;text-transform:uppercase}.card-detail__value{display:block;min-width:0;color:var(--p-list-foreground);font-size:.94rem;font-weight:800;line-height:1.2;overflow-wrap:normal;word-break:normal}.card-detail__value,.card-detail__value *{white-space:nowrap}.card-detail--balance .card-detail__value{color:var(--md-sys-color-primary)}.card-detail--limit .card-detail__value{color:var(--md-sys-color-error)}.card-detail--risk .card-detail__value{color:var(--md-sys-color-tertiary, var(--p-list-foreground))}.item-card:hover{box-shadow:var(--md-sys-elevation-level3);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-card:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.card-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:6px 8px 4px;border-top:1px solid var(--md-sys-color-outline-variant);margin-top:auto}.status-overlay{position:absolute;top:14px;right:14px;max-width:min(42%,148px);overflow:hidden;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto;width:100%;min-width:0;max-width:100%}.status-overlay .mdc-evolution-chip__text-label,.status-overlay .mat-mdc-chip-action-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.leading-icon.mat-icon,.list-item-leading>mat-icon,.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon],[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon]{width:36px;height:36px;min-width:36px;line-height:36px;font-size:19px;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;box-sizing:border-box;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 15%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 30%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary));box-shadow:inset 0 1px #ffffff0f}.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon,[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon{font-size:19px;width:19px;height:19px;line-height:19px;color:inherit}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);--mdc-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mdc-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );font-size:var(--p-list-chip-font-size);font-weight:600;letter-spacing:.02em;border-radius:999px!important;background-color:var(--p-list-chip-background, var(--md-sys-color-surface-container-high))!important;color:var(--p-list-chip-color, var(--md-sys-color-on-surface))!important;border:1px solid var(--p-list-chip-border-color, transparent)!important}:host ::ng-deep .mat-mdc-chip .mdc-evolution-chip__text-label,:host ::ng-deep .mat-mdc-chip .mat-mdc-chip-action-label{color:var(--p-list-chip-color, inherit)!important;font-weight:600;font-size:.72rem;letter-spacing:.02em}.meta .mat-icon{font-size:18px;height:18px;width:18px}.features{overflow:hidden}@keyframes shimmer{0%{background-position:-468px 0}to{background-position:468px 0}}.skeleton{animation-duration:1.2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear;background:linear-gradient(to right,var(--md-sys-color-surface-container-low) 8%,var(--md-sys-color-surface-container) 18%,var(--md-sys-color-surface-container-low) 33%);background-size:800px 104px;position:relative}.skeleton-avatar{width:32px;height:32px;border-radius:50%}.skeleton-line{height:10px;margin:6px 0;border-radius:6px}.skeleton-chip{width:48px;height:18px;border-radius:999px}.chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important;color:var(--p-list-chip-color, currentColor)!important}.w-60{width:60%}.w-40{width:40%}.list-collection-toolbar{display:flex;align-items:center;gap:12px;padding:12px;margin-bottom:8px;color:var(--p-list-foreground);background:var(--p-list-surface-low);border:var(--p-list-border);border-radius:calc(var(--p-list-radius) * .75)}.list-toolbar-search{flex:1 1 320px;min-width:220px;max-width:440px}.list-toolbar-commands{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;margin-inline-start:auto}.list-toolbar-commands button{border-radius:8px}.list-toolbar-commands button .mat-icon{margin-right:6px}.list-toolbar-sort{width:200px}.list-remote-error{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;margin:8px 4px 0;padding:16px;color:var(--md-sys-color-on-error-container);background:var(--md-sys-color-error-container);border-radius:calc(var(--p-list-radius) * .75)}.list-remote-error__copy{display:flex;flex-direction:column;gap:4px;min-width:0}.list-remote-error__copy span{color:color-mix(in srgb,var(--md-sys-color-on-error-container) 82%,transparent);line-height:1.45}.list-remote-error button{color:var(--md-sys-color-on-error-container);--mat-button-outlined-label-text-color: var( --md-sys-color-on-error-container );--mat-button-outlined-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent );--mdc-outlined-button-label-text-color: var( --md-sys-color-on-error-container );--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent )}.mat-mdc-paginator{margin-top:14px;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--p-list-surface-low);color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-container{min-height:40px;padding:4px 8px;gap:6px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select{margin-left:8px;width:92px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-text-field-wrapper{--mdc-outlined-text-field-container-color: color-mix( in srgb, var(--p-list-surface-low) 92%, var(--md-sys-color-on-surface) 8% );--mdc-outlined-text-field-input-text-color: var(--p-list-foreground);min-height:40px;padding-inline:12px 8px;background:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;background-color:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;color:var(--p-list-foreground)!important}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-form-field-infix{min-height:40px;padding-block:8px;width:auto}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-select-trigger{min-height:24px;padding-right:2px;color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-range-label,:host ::ng-deep .mat-mdc-paginator .mat-mdc-select-value-text{font-size:12px;color:var(--p-list-foreground-muted)}.list-paginator-total{margin-top:14px;padding:4px 8px 0;font-size:12px;color:var(--p-list-foreground-muted)}:host ::ng-deep .mat-mdc-paginator.hide-range .mat-mdc-paginator-range-label{display:none}::ng-deep .praxis-list-paginator-select-panel.mat-mdc-select-panel{--mat-select-panel-background-color: var( --md-sys-color-surface-container, var(--mat-sys-surface-container) );background:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;background-color:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #d7dbe5) 70%,transparent);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, #000) 28%,transparent)}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option{--mat-option-label-text-color: var(--md-sys-color-on-surface, #111827);color:var(--md-sys-color-on-surface, #111827)!important}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option.mat-mdc-option-active{--mat-option-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-primary, #2f7cff) 14%, transparent );background:color-mix(in srgb,var(--md-sys-color-primary, #2f7cff) 14%,transparent)!important;color:var(--md-sys-color-on-surface, #111827)!important}.muted{color:var(--p-list-foreground-muted)}@container (max-width: 720px){.executive-inline-skin .list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.executive-inline-skin .list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--primary,.executive-inline-skin .list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.executive-inline-skin .list-item-content--row-layout .list-row-slot--meta,.executive-inline-skin .list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.executive-inline-skin .list-selection-control{padding-left:0}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.executive-inline-skin .list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.executive-inline-skin .list-item-trailing .list-item-actions{margin-inline-start:auto}.executive-inline-skin .item-expansion{margin-left:0;margin-right:0}.executive-inline-skin .list-collection-toolbar{flex-direction:column;align-items:stretch}.executive-inline-skin .list-toolbar-search,.executive-inline-skin .list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.executive-inline-skin .list-toolbar-commands{width:100%;margin-inline-start:0}.executive-inline-skin .list-toolbar-sort{flex:1 1 100%}.executive-inline-skin .list-toolbar-commands button{flex:0 0 auto}.executive-inline-skin .list-remote-error{grid-template-columns:auto minmax(0,1fr)}.executive-inline-skin .list-remote-error button{grid-column:1/-1;justify-self:stretch}}@container (max-width: 420px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}@media(max-width:640px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}.list-loading-status{display:flex;align-items:center;gap:8px;padding:12px 0;color:inherit;--mat-progress-spinner-active-indicator-color: currentColor}.list-loading-status:empty{display:none}.praxis-list-virtual-viewport,.praxis-list-bounded-viewport{display:block;width:100%;overflow-y:auto;outline:none;padding-right:4px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent) transparent}.praxis-list-virtual-viewport::-webkit-scrollbar,.praxis-list-bounded-viewport::-webkit-scrollbar{width:6px;height:6px}.praxis-list-virtual-viewport::-webkit-scrollbar-track,.praxis-list-bounded-viewport::-webkit-scrollbar-track{background:transparent}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent);border-radius:999px}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb:hover,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, #94a3b8) 72%,transparent)}.praxis-list-virtual-viewport{height:var(--p-list-viewport-height, 400px);contain:strict}.praxis-list-virtual-viewport .praxis-list-virtual-list{padding-top:0;padding-bottom:0}.list-item-menu-trigger{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--md-sys-shape-corner-full, 9999px);color:var(--p-list-foreground-muted, inherit);transition:background-color .15s ease,color .15s ease}.list-item-menu-trigger:hover{background-color:var(--p-list-item-hover-surface, rgba(0, 0, 0, .04));color:var(--p-list-foreground, inherit)}\n"] }]
|
|
13396
|
+
], template: "<div class=\"list-loading-status\" role=\"status\">\n @if (loading$ | async) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\" aria-hidden=\"true\"></mat-progress-spinner>\n <span>{{ t('loading', 'Carregando itens\u2026') }}</span>\n }\n</div>\n<div\n class=\"praxis-list-root\"\n tabindex=\"-1\"\n [attr.aria-busy]=\"(loading$ | async) ? 'true' : 'false'\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.data-item-appearance]=\"config?.layout?.itemAppearance || null\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (enableCustomization) {\n <div class=\"list-assistant\">\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openConfigEditor()\"\n [matTooltip]=\"configEditorLabel()\"\n [attr.aria-label]=\"configEditorLabel()\"\n data-testid=\"praxis-list-open-config-editor\"\n >\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n (click)=\"openAiAssistant()\"\n matTooltip=\"Copiloto semantico Praxis\"\n aria-label=\"Abrir copiloto semantico Praxis da lista\"\n data-testid=\"praxis-list-ai-assistant-trigger\"\n >\n <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"\n aiAssistantViewState.state === 'processing' ||\n aiAssistantViewState.state === 'applying'\n \"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-list-ai-assistant\"\n panelTestId=\"praxis-list-ai-assistant-panel\"\n submitTestId=\"praxis-list-ai-assistant-submit\"\n applyTestId=\"praxis-list-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n\n @if (\n config.export?.enabled ||\n (isRemoteDataMode() &&\n (config.ui?.showSort ||\n (config.ui?.showSearch && config.ui?.searchField)))\n ) {\n <div\n class=\"list-collection-toolbar\"\n role=\"group\"\n [attr.aria-label]=\"t('toolbar.label', 'Controles da lista')\"\n >\n @if (\n isRemoteDataMode() && config.ui?.showSearch && config.ui?.searchField\n ) {\n <mat-form-field\n class=\"list-toolbar-search\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{\n config.ui?.searchPlaceholder || t(\"toolbar.search\", \"Buscar\")\n }}</mat-label>\n <mat-icon matPrefix [praxisIcon]=\"'search'\"></mat-icon>\n <input\n #searchInput\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n\n <div class=\"list-toolbar-commands\">\n @if (isRemoteDataMode() && config.ui?.showSort) {\n <mat-form-field\n class=\"list-toolbar-sort\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n >\n <mat-label>{{ t(\"toolbar.sort\", \"Ordenar por\") }}</mat-label>\n @let activeSort = activeSortValue((page$ | async)?.sort);\n <mat-select\n [value]=\"activeSort\"\n (selectionChange)=\"onSortChange($event.value)\"\n >\n @if (activeSort && !hasSortOption(activeSort)) {\n <mat-option [value]=\"activeSort\">{{ activeSort }}</mat-option>\n }\n @for (op of config.ui?.sortOptions || []; track $index) {\n <mat-option [value]=\"sortOptionValue(op)\">{{\n sortOptionLabel(op)\n }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (config.export?.enabled) {\n <button\n mat-stroked-button\n type=\"button\"\n [matMenuTriggerFor]=\"listExportMenu\"\n [attr.aria-label]=\"t('export.button', 'Exportar')\"\n [disabled]=\"exportBusy\"\n [attr.aria-busy]=\"exportBusy\"\n >\n <mat-icon [praxisIcon]=\"'download'\"></mat-icon>\n {{ t(\"export.button\", \"Exportar\") }}\n </button>\n <span class=\"cdk-visually-hidden\" aria-live=\"polite\">\n {{ exportStatusMessage }}\n </span>\n <mat-menu #listExportMenu=\"matMenu\">\n @for (format of listExportFormats(); track format) {\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"onExportAction(format)\"\n >\n <mat-icon [praxisIcon]=\"exportIcon(format)\"></mat-icon>\n {{ format.toUpperCase() }}\n </button>\n }\n </mat-menu>\n }\n </div>\n </div>\n }\n\n <!-- Skeleton while loading -->\n @if (loading$ | async) {\n @if (hasSkeleton()) {\n @if (isListVariant()) {\n <mat-list>\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <mat-list-item>\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else {\n <div class=\"cards-grid\">\n @for (_ of skeletonItems(); track $index; let i = $index) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n <div class=\"list-item-leading\">\n <div class=\"skeleton skeleton-avatar\"></div>\n </div>\n <div class=\"list-item-text\">\n <div class=\"skeleton skeleton-line w-60\"></div>\n @if (layoutLines > 1) {\n <div class=\"skeleton skeleton-line w-40\"></div>\n }\n </div>\n <div class=\"list-item-trailing\">\n <div class=\"skeleton skeleton-chip\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (error$ | async; as remoteError) {\n <div class=\"list-remote-error\" role=\"alert\">\n <mat-icon [praxisIcon]=\"'error_outline'\"></mat-icon>\n <div class=\"list-remote-error__copy\">\n <strong>{{\n t(\"remoteError.title\", \"N\u00E3o foi poss\u00EDvel carregar a lista\")\n }}</strong>\n <span>\n {{\n remoteError.filtered\n ? t(\n \"remoteError.filteredDescription\",\n \"Os filtros permanecem aplicados. Nenhum dado sem filtro foi exibido.\"\n )\n : t(\n \"remoteError.description\",\n \"Verifique a conex\u00E3o e tente novamente.\"\n )\n }}\n </span>\n </div>\n <button mat-stroked-button type=\"button\" (click)=\"retryRemoteData()\">\n {{ t(\"remoteError.retry\", \"Tentar novamente\") }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0 && !(error$ | async)) {\n @if (hasCustomEmptyStateTemplate()) {\n <div\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n >\n @if (emptyStateTemplate(); as empty) {\n @if (\n simpleRichContentNodes(empty, {\n imageAlt: config.templating?.emptyState?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (empty.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"empty.value\"\n [ngClass]=\"empty.class\"\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [style.cssText]=\"\n (empty.style ? empty.style + ';' : '') +\n iconStyle(empty.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n >\n <img\n [src]=\"empty.value\"\n [alt]=\"config.templating?.emptyState?.imageAlt || ''\"\n />\n @if (empty.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(empty.badge?.color)\n ? empty.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (empty.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(empty.badge?.color, empty.badge?.variant)\n \"\n >{{ empty.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(empty.color) ? empty.color : undefined\n \"\n [ngClass]=\"[\n empty.class || '',\n (empty.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(empty.color, empty.variant) +\n (empty.style ? ';' + empty.style : '')\n \"\n >{{ empty.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">\n @for (\n _ of ratingRange(empty);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, empty.value)\"\n [color]=\"ratingThemeColor(empty)\"\n [style.cssText]=\"ratingIconStyle(empty)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"empty.class\"\n [style.cssText]=\"empty.style\"\n [innerHTML]=\"empty.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"empty\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"empty\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"empty\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"empty.class\" [style.cssText]=\"empty.style\">{{\n empty.value\n }}</span>\n }\n }\n }\n }\n </div>\n } @else {\n <praxis-empty-state-card\n class=\"section-header\"\n [class.section-header--setup]=\"isResourceConnectionMissing()\"\n [icon]=\"emptyStateIcon()\"\n [title]=\"emptyStateTitle()\"\n [description]=\"emptyStateDescription()\"\n [primaryAction]=\"emptyStatePrimaryAction()\"\n [secondaryActions]=\"emptyStateSecondaryActions()\"\n />\n }\n }\n }\n\n <ng-template\n #rowLayoutNode\n let-node\n let-slot=\"slot\"\n let-imageAlt=\"imageAlt\"\n >\n @if (\n simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt });\n as richNodes\n ) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"[\n slot === 'leading' ? 'leading-icon' : '',\n node?.class || '',\n ]\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\n slot === 'leading'\n ? leadingIconStyle(node?.color, node?.style)\n : (node?.style || '' ? node.style + ';' : '') +\n iconStyle(node?.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n >\n <img\n [src]=\"node?.value\"\n [alt]=\"node?.imageAlt || imageAlt || ''\"\n />\n @if (node?.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(node?.badge?.color)\n ? node?.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (node?.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(node?.badge?.color, node?.badge?.variant)\n \"\n >\n {{ node?.badge?.value }}\n </mat-chip>\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [ngClass]=\"[\n node?.class || '',\n (node?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(node?.color, node?.variant) +\n (node?.style ? ';' + node.style : '')\n \"\n >\n {{ node?.value }}\n </mat-chip>\n }\n @case (\"rating\") {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @for (_ of ratingRange(node); track $index; let idx = $index) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, node?.value)\"\n [color]=\"ratingThemeColor(node)\"\n [style.cssText]=\"ratingIconStyle(node)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"node?.class\"\n [style.cssText]=\"node?.style\"\n [innerHTML]=\"node?.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"node\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose [compose]=\"node\"></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"node\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"node?.class\" [style.cssText]=\"node?.style\">\n @if (\n slot === \"meta\" && config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\n }\n </ng-template>\n\n <ng-template #featureContent let-item let-feature=\"feature\">\n @if (featureTemplateNode(item, feature); as featureNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: featureNode,\n slot: 'feature',\n imageAlt: feature?.imageAlt || '',\n }\n \"\n ></ng-container>\n } @else if (featureRichContentNodes(item, feature); as featureNodes) {\n <praxis-rich-content layout=\"inline\" [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (feature.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"feature.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"feature.class\" [style.cssText]=\"feature.style\">\n @for (line of featureLabelLines(item, feature.expr); track $index) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, feature.expr, feature.class);\n as progress\n ) {\n <span class=\"feature-progress\" aria-hidden=\"true\">\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\n </ng-template>\n\n <ng-template\n #listRowLayout\n let-item\n let-index=\"index\"\n let-sectionKey=\"sectionKey\"\n let-clickable=\"clickable\"\n >\n <div\n class=\"list-item-content\"\n [ngClass]=\"rowLayoutItemClass(item)\"\n [attr.style]=\"rowLayoutItemStyle(item)\"\n >\n @if (clickable) {\n <button\n type=\"button\"\n class=\"list-row-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, index) : null\n \"\n (click)=\"onRowActivate(item, index, sectionKey)\"\n ></button>\n }\n @for (\n column of rowLayoutColumns();\n track rowLayoutTrackColumn($index, column)\n ) {\n <div\n [attr.data-row-slot]=\"column.slot\"\n [ngClass]=\"rowLayoutColumnClass(column)\"\n [attr.style]=\"rowLayoutColumnStyle(column)\"\n >\n @if (column.slot === \"leading\") {\n @if (rowLayoutSlot(item, column.slot); as lead) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: lead,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n } @else if (column.slot === \"trailing\") {\n @if (rowLayoutSlot(item, column.slot); as trailingNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: trailingNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"rowActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #rowActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, index)\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n } @else if (column.slot === \"actions\") {\n @if ((visibleActions(item, \"actions\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"actions\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, index)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, item, index)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"\n onActionClick($event, action.id, item, index)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, index)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n index\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, index)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n } @else if (column.slot === \"expand\") {\n @if (showExpandIcon(\"expand\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, index)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon() ? expandRegionId(item, index) : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n ></button>\n }\n } @else if (rowLayoutSlot(item, column.slot); as slotNode) {\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: slotNode,\n slot: column.slot,\n imageAlt: rowLayoutImageAlt(column.slot),\n }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- List variant -->\n @if (isListVariant()) {\n <!-- Selection and row actions share one neutral list shell so every\n interactive affordance remains a sibling keyboard target. -->\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n\n <!-- Unified list surface -->\n <ng-template #readList>\n @if (isVirtualScrollEnabled()) {\n <cdk-virtual-scroll-viewport\n class=\"praxis-list-virtual-viewport\"\n [itemSize]=\"virtualScrollItemSize()\"\n [minBufferPx]=\"virtualScrollMinBufferPx()\"\n [maxBufferPx]=\"virtualScrollMaxBufferPx()\"\n [style.height]=\"virtualScrollViewportHeight()\"\n >\n <mat-list\n class=\"praxis-list-virtual-list\"\n role=\"list\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n <mat-list-item\n *cdkVirtualFor=\"\n let item of virtualScrollItems(sections$ | async, items$ | async);\n let i = index;\n trackBy: trackByVirtualItem\n \"\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n </mat-list>\n </cdk-virtual-scroll-viewport>\n } @else {\n <mat-list\n role=\"list\"\n [class.praxis-list-bounded-viewport]=\"hasBoundedScrollViewport()\"\n [style.max-height]=\"hasBoundedScrollViewport() ? virtualScrollViewportHeight() : null\"\n [attr.aria-label]=\"\n isSelectionEnabled()\n ? selectionListAriaLabel()\n : config.a11y?.ariaLabel || null\n \"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section);\n let sidx = $index\n ) {\n @if (section.key) {\n <div class=\"section-header mat-subheader\">\n @if (sectionHeaderTemplate(section.key); as sh) {\n @if (\n simpleRichContentNodes(sh, {\n imageAlt:\n config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (sh.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"sh.value\"\n [ngClass]=\"sh.class\"\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') +\n iconStyle(sh.color)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <span\n class=\"inline-image\"\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n >\n <img\n [src]=\"sh.value\"\n [alt]=\"\n config.templating?.sectionHeader?.imageAlt || ''\n \"\n />\n @if (sh.badge?.value) {\n <mat-chip\n class=\"inline-badge\"\n [color]=\"\n isThemeColor(sh.badge?.color)\n ? sh.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (sh.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(sh.badge?.color, sh.badge?.variant)\n \"\n >{{ sh.badge?.value }}</mat-chip\n >\n }\n </span>\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(sh.color) ? sh.color : undefined\n \"\n [ngClass]=\"[\n sh.class || '',\n (sh.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : '',\n ]\"\n [style.cssText]=\"\n chipStyle(sh.color, sh.variant) +\n (sh.style ? ';' + sh.style : '')\n \"\n >{{ sh.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">\n @for (\n _ of ratingRange(sh);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, sh.value)\"\n [color]=\"ratingThemeColor(sh)\"\n [style.cssText]=\"ratingIconStyle(sh)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"sh.class\"\n [style.cssText]=\"sh.style\"\n [innerHTML]=\"sh.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"sh\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"sh\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"sh\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span [ngClass]=\"sh.class\" [style.cssText]=\"sh.style\">{{\n sh.value\n }}</span>\n }\n }\n }\n }\n </div>\n }\n @for (\n item of section.items;\n track trackByItem($index, item);\n let i = $index\n ) {\n <mat-list-item\n role=\"listitem\"\n [attr.data-item-status]=\"item?.status || null\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n listItemBody;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n }\n \"\n ></ng-container>\n </mat-list-item>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider\n role=\"presentation\"\n aria-hidden=\"true\"\n ></mat-divider>\n }\n }\n }\n </mat-list>\n }\n </ng-template>\n\n <ng-template #listItemBody let-item let-i=\"index\" let-sectionKey=\"sectionKey\">\n <div\n class=\"list-row-shell\"\n [class.list-row-shell--selectable]=\"isSelectionEnabled()\"\n [class.list-row-shell--with-control]=\"shouldShowSelectionControl()\"\n [class.list-row-shell--selected]=\"isItemSelected(item)\"\n [class.list-row-shell--expanded]=\"isExpandable() && isExpanded(item, i)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: sectionKey,\n clickable: true,\n }\n \"\n ></ng-container>\n } @else {\n <div\n class=\"list-item-content\"\n [ngClass]=\"itemRuleClass(item)\"\n [attr.style]=\"itemRuleStyle(item)\"\n >\n <button\n type=\"button\"\n class=\"list-item-main-action\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n [attr.aria-expanded]=\"\n expansionOwnedByRow() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByRow() ? expandRegionId(item, i) : null\n \"\n (click)=\"\n onRowActivate(item, i, sectionKey)\n \"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt:\n config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"\n config.templating?.leading?.imageAlt ||\n ''\n \"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color)\n ? lead.color\n : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(lead.color, lead.variant)\n \"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(item)?.class\"\n [style.cssText]=\"primary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(primary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(item)\"\n ></praxis-list-metric>\n } @else if (primary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(item)\"\n ></praxis-list-compose>\n } @else if (primary(item)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(item)\"\n ></praxis-list-runtime-component>\n } @else if (primary(item)?.type === \"html\") {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(item)?.class\"\n [style.cssText]=\"secondary(item)?.style\"\n >\n @if (\n simpleRichContentNodes(secondary(item));\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (\n item.segmentVariant &&\n item.segmentLabel &&\n item.accountType &&\n item.since\n ) {\n <!-- Component-based rendering for executive items -->\n <span class=\"exec-subline\">\n <praxis-executive-badge\n [variant]=\"item.segmentVariant\"\n [label]=\"item.segmentLabel\"\n ></praxis-executive-badge>\n <span class=\"exec-subcopy\">{{\n item.accountType\n }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\"\n >Desde {{ item.since }}</span\n >\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span\n [innerHTML]=\"secondary(item)?.value\"\n ></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\n } @else if (secondary(item)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(item)\"\n ></praxis-list-compose>\n } @else if (\n secondary(item)?.type === \"component\"\n ) {\n <praxis-list-runtime-component\n [component]=\"secondary(item)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (meta(item); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n config.templating?.metaPrefixIcon;\n as mpi\n ) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: item, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n </div>\n </button>\n <div class=\"list-item-trailing\">\n @if (meta(item); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, { slot: \"meta\" });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(m.color, m.variant)\n \"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color)\n ? m.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"m.value\"\n [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon\n [praxisIcon]=\"mpi2\"\n ></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(item); as tr) {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt:\n config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr.color, tr.variant)\n \"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color)\n ? tr.color\n : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt ||\n ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n @if (\n item.alertsData !== undefined &&\n item.ownerName\n ) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts\n [alerts]=\"item.alertsData\"\n ></praxis-executive-alerts>\n <praxis-executive-owner\n [name]=\"item.ownerName\"\n ></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n isExpanded(item, i)\n ? 'expand_less'\n : 'expand_more'\n \"\n size=\"compact\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon()\n ? isExpanded(item, i)\n : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n ></button>\n }\n @if ((visibleActions(item, \"trailing\") || []).length || (visibleActions(item, \"menu\") || []).length) {\n <div\n class=\"list-item-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(item, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"\n action.icon || 'more_horiz'\n \"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, item, i)\"\n [style.cssText]=\"\n actionIconStyle(action.color)\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'stroked')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'raised')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant ||\n action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n [style.cssText]=\"\n buttonStyle(action.color, 'flat')\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"\n action.label || action.id\n \"\n [disabled]=\"\n isActionLoading(action.id, item, i)\n \"\n [ngClass]=\"{\n 'action-loading': isActionLoading(\n action.id,\n item,\n i\n ),\n }\"\n >\n @if (isActionLoading(action.id, item, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n @if ((visibleActions(item, \"menu\") || []).length) {\n <button\n type=\"button\"\n praxisIconButton=\"more_vert\"\n size=\"compact\"\n [matMenuTriggerFor]=\"itemActionsMenu\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n class=\"list-item-menu-trigger\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n <mat-menu #itemActionsMenu=\"matMenu\">\n @for (action of visibleActions(item, \"menu\"); track action?.id ?? $index) {\n <button\n mat-menu-item\n (click)=\"onActionClick($event, action.id, item, i)\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\n >\n @if (action.icon) {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n <span>{{ action.label || action.id }}</span>\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (shouldShowSelectionControl()) {\n <div class=\"list-selection-control\">\n @if (config.selection?.mode === \"multiple\") {\n <mat-checkbox\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, $event.checked)\"\n ></mat-checkbox>\n } @else {\n <mat-radio-button\n [name]=\"selectionControlName()\"\n [checked]=\"isItemSelected(item)\"\n [disabled]=\"boundControl.disabled\"\n [aria-label]=\"selectionControlAriaLabel(item)\"\n (change)=\"setItemSelected(item, true)\"\n ></mat-radio-button>\n }\n </div>\n }\n </div>\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\n [ngClass]=\"expansionRenderingClasses()\"\n [style]=\"expansionRenderingStyle()\"\n [id]=\"expandRegionId(item, i)\"\n role=\"region\"\n [attr.aria-label]=\"expansionRegionAriaLabel(item)\"\n >\n <div class=\"item-expansion-grid\">\n @for (\n expansionSection of expansionSections(item);\n track expansionSection.id\n ) {\n <section\n class=\"expansion-section\"\n [attr.data-section-type]=\"expansionSection.type\"\n >\n @if (expansionSection.title) {\n <div class=\"expansion-section-title\">\n {{ expansionSection.title }}\n </div>\n }\n @if (\n expansionSectionHasContent(\n item,\n expansionSection,\n i\n )\n ) {\n @switch (expansionSection.type) {\n @case (\"chip-list\") {\n <div class=\"expansion-chip-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <mat-chip class=\"expansion-chip\">{{\n expansionItemLabel(expansionEntry)\n }}</mat-chip>\n }\n </div>\n }\n @case (\"timeline\") {\n <div class=\"expansion-timeline\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-timeline-item\">\n <div class=\"expansion-timeline-title\">\n {{\n expansionTimelineTitle(expansionEntry)\n }}\n </div>\n @if (\n expansionTimelineMeta(expansionEntry)\n ) {\n <div class=\"expansion-timeline-meta\">\n {{\n expansionTimelineMeta(\n expansionEntry\n )\n }}\n </div>\n }\n @if (\n expansionTimelineDescription(\n expansionEntry\n )\n ) {\n <div\n class=\"expansion-timeline-description\"\n >\n {{\n expansionTimelineDescription(\n expansionEntry\n )\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n @case (\"key-value\") {\n <dl class=\"expansion-key-value\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-key-value-row\">\n @if (\n expansionKeyValueKey(expansionEntry)\n ) {\n <dt>\n {{\n expansionKeyValueKey(expansionEntry)\n }}\n </dt>\n }\n <dd>\n {{\n expansionKeyValueValue(expansionEntry)\n }}\n </dd>\n </div>\n }\n </dl>\n }\n @case (\"rich-content\") {\n @if (\n expansionRichContentDocument(\n item,\n expansionSection,\n i\n );\n as richExpansionDocument\n ) {\n <praxis-rich-content\n [document]=\"richExpansionDocument\"\n [context]=\"\n expansionRichContentContext(\n item,\n expansionSection,\n i\n )\n \"\n [hostCapabilities]=\"\n expansionRichContentHostCapabilities(\n item,\n expansionSection,\n i\n )\n \"\n rootClassName=\"praxis-list-expansion-rich-content\"\n ></praxis-rich-content>\n }\n }\n @default {\n <div class=\"expansion-info-list\">\n @for (\n expansionEntry of expansionSectionItems(\n item,\n expansionSection,\n i\n );\n track $index\n ) {\n <div class=\"expansion-info-item\">\n <div class=\"expansion-info-title\">\n {{ expansionInfoTitle(expansionEntry) }}\n </div>\n @if (expansionInfoValue(expansionEntry)) {\n <div class=\"expansion-info-value\">\n {{\n expansionInfoValue(expansionEntry)\n }}\n </div>\n }\n </div>\n }\n </div>\n }\n }\n } @else {\n <div class=\"expansion-empty\">\n {{\n expansionSection.emptyLabel ||\n \"Sem dados dispon\u00EDveis\"\n }}\n </div>\n }\n </section>\n }\n </div>\n </div>\n }\n </ng-template>\n } @else if (isTilesVariant()) {\n <ng-container *ngTemplateOutlet=\"tilesVariant\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"cardsVariant\"></ng-container>\n }\n\n <!-- Cards variant -->\n <ng-template #cardsVariant>\n <div class=\"cards-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-card\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"list-item-content card-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n slot: \"leading\",\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-icon\n class=\"leading-icon\"\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n leadingIconStyle(lead.color, lead.style)\n \"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n @if (lead.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(lead.badge?.color)\n ? lead.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (lead.badge?.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n lead.badge?.color,\n lead.badge?.variant\n )\n \"\n >{{ lead.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n } @else {\n <span class=\"leading-placeholder\"></span>\n }\n </div>\n <div class=\"list-item-text\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n @if (\n (config.templating?.metaPlacement === \"line\" &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\"))\n ) {\n <div\n class=\"tertiary\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ m.value }}\n </div>\n }\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (detail of detailSlots; track detail.slot) {\n <div\n class=\"card-detail\"\n [ngClass]=\"'card-detail--' + detail.slot\"\n >\n <span class=\"card-detail__label\">{{\n detail.label\n }}</span>\n <span class=\"card-detail__value\">\n <ng-container\n *ngTemplateOutlet=\"\n rowLayoutNode;\n context: {\n $implicit: detail.node,\n slot: detail.slot,\n imageAlt: rowLayoutImageAlt(detail.slot),\n }\n \"\n ></ng-container>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n <div class=\"list-item-trailing\">\n @if (meta(it); as m) {\n @if (\n !(\n (config.templating?.metaPlacement === \"line\" ||\n layoutLines > 2) &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\n m?.type === \"datetime\" ||\n m?.type === \"relative\" ||\n m?.type === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"m\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>\n @if (config.templating?.metaPrefixIcon; as mpi2) {\n <mat-icon [praxisIcon]=\"mpi2\"></mat-icon>\n }\n {{ m.value }}</span\n >\n }\n }\n }\n </div>\n }\n }\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"status-overlay\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n } @else {\n <div\n class=\"trailing\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n @if (\n simpleRichContentNodes(tr, {\n imageAlt: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <div\n class=\"lead-image\"\n [ngClass]=\"tr.class\"\n [style.cssText]=\"tr.style\"\n >\n <img\n [src]=\"tr.value\"\n [alt]=\"\n config.templating?.trailing?.imageAlt || ''\n \"\n />\n @if (tr.badge?.value) {\n <mat-chip\n class=\"lead-badge\"\n [color]=\"\n isThemeColor(tr.badge?.color)\n ? tr.badge?.color\n : undefined\n \"\n [ngClass]=\"\n (tr.badge?.variant || 'filled') ===\n 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(\n tr.badge?.color,\n tr.badge?.variant\n )\n \"\n >{{ tr.badge?.value }}</mat-chip\n >\n }\n </div>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr.value)\"\n [color]=\"ratingThemeColor(tr)\"\n [style.cssText]=\"ratingIconStyle(tr)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Tiles variant -->\n <ng-template #tilesVariant>\n <div class=\"tiles-grid\">\n @for (it of (items$ | async) ?? []; track $index; let i = $index) {\n <div\n class=\"item-tile\"\n [ngClass]=\"itemRuleClass(it)\"\n [attr.style]=\"itemRuleStyle(it)\"\n >\n <div\n class=\"tile-main-action\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"itemAriaLabel(it)\"\n (click)=\"onItemClick(it, i)\"\n (keydown.enter)=\"onItemClick(it, i)\"\n (keydown.space)=\"$event.preventDefault(); onItemClick(it, i)\"\n >\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"image\") {\n <img\n [src]=\"lead.value\"\n [alt]=\"config.templating?.leading?.imageAlt || ''\"\n />\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"lead.value\"\n [ngClass]=\"lead.class\"\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [style.cssText]=\"\n (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\n \"\n ></mat-icon>\n }\n @case (\"text\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(lead.color) ? lead.color : undefined\n \"\n [ngClass]=\"\n (lead.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(lead.color, lead.variant)\"\n >{{ lead.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >\n @for (\n _ of ratingRange(lead);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, lead.value)\"\n [color]=\"ratingThemeColor(lead)\"\n [style.cssText]=\"ratingIconStyle(lead)\"\n ></mat-icon>\n }\n </span>\n }\n @case (\"html\") {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n [innerHTML]=\"lead.value\"\n ></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"lead\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"lead\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"lead\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span\n [ngClass]=\"lead.class\"\n [style.cssText]=\"lead.style\"\n >{{ lead.value }}</span\n >\n }\n }\n }\n }\n </div>\n\n @if (trailing(it); as tr) {\n @if (\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr?.type === \"chip\" || tr?.type === \"icon\")\n ) {\n <div class=\"tile-status\">\n @if (simpleRichContentNodes(tr); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [ngClass]=\"\n (tr.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(tr.color, tr.variant)\"\n >{{ tr.value }}</mat-chip\n >\n }\n @if (tr?.type === \"icon\") {\n <mat-icon\n [praxisIcon]=\"tr.value\"\n [color]=\"\n isThemeColor(tr.color) ? tr.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr.color)\"\n ></mat-icon>\n }\n }\n </div>\n }\n }\n\n <div class=\"tile-body\">\n <div\n class=\"primary\"\n [ngClass]=\"primary(it)?.class\"\n [style.cssText]=\"primary(it)?.style\"\n >\n @if (simpleRichContentNodes(primary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"primary(it)\"\n ></praxis-list-metric>\n } @else if (primary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"primary(it)\"\n ></praxis-list-compose>\n } @else if (primary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"primary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if (layoutLines > 1) {\n <div\n class=\"secondary\"\n [ngClass]=\"secondary(it)?.class\"\n [style.cssText]=\"secondary(it)?.style\"\n >\n @if (simpleRichContentNodes(secondary(it)); as richNodes) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else if (secondary(it)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(it)\"\n ></praxis-list-metric>\n } @else if (secondary(it)?.type === \"compose\") {\n <praxis-list-compose\n [compose]=\"secondary(it)\"\n ></praxis-list-compose>\n } @else if (secondary(it)?.type === \"component\") {\n <praxis-list-runtime-component\n [component]=\"secondary(it)\"\n ></praxis-list-runtime-component>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n\n @if (meta(it); as m) {\n <div\n class=\"tile-meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n @if (\n simpleRichContentNodes(m, {\n slot: \"meta\",\n imageAlt: m.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [ngClass]=\"\n (m.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"chipStyle(m.color, m.variant)\"\n >{{ m.value }}</mat-chip\n >\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(m);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, m.value)\"\n [color]=\"ratingThemeColor(m)\"\n [style.cssText]=\"ratingIconStyle(m)\"\n ></mat-icon>\n }\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"m.value\"\n [color]=\"\n isThemeColor(m.color) ? m.color : undefined\n \"\n [style.cssText]=\"iconStyle(m.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\"\n /></span>\n }\n @case (\"html\") {\n <span [innerHTML]=\"m.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"m\"></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"m\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"m\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ m.value }}</span>\n }\n }\n }\n </div>\n }\n\n @if (featuresVisible()) {\n <div class=\"tiles-features\">\n @for (\n f of config.templating?.features || [];\n track $index;\n let fi = $index\n ) {\n <span\n class=\"feature\"\n [ngClass]=\"featureSemanticClass(it, f.expr, f.class)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n featureContent;\n context: { $implicit: it, feature: f }\n \"\n ></ng-container>\n </span>\n }\n </div>\n }\n\n @if (trailing(it); as tr2) {\n @if (\n !(\n (config.templating?.statusPosition || \"inline\") ===\n \"top-right\" &&\n (tr2?.type === \"chip\" || tr2?.type === \"icon\")\n )\n ) {\n <div\n class=\"tile-trailing\"\n [ngClass]=\"tr2.class\"\n [style.cssText]=\"tr2.style\"\n >\n @if (\n simpleRichContentNodes(tr2, {\n imageAlt: tr2.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content\n layout=\"inline\"\n [nodes]=\"richNodes\"\n ></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [ngClass]=\"\n (tr2.variant || 'filled') === 'outlined'\n ? 'chip-outlined'\n : ''\n \"\n [style.cssText]=\"\n chipStyle(tr2.color, tr2.variant)\n \"\n >{{ tr2.value }}</mat-chip\n >\n }\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"tr2.value\"\n [color]=\"\n isThemeColor(tr2.color) ? tr2.color : undefined\n \"\n [style.cssText]=\"iconStyle(tr2.color)\"\n ></mat-icon>\n }\n @case (\"image\") {\n <span class=\"inline-image\"\n ><img\n [src]=\"tr2.value\"\n [alt]=\"tr2.imageAlt || ''\"\n /></span>\n }\n @case (\"rating\") {\n @for (\n _ of ratingRange(tr2);\n track $index;\n let idx = $index\n ) {\n <mat-icon\n [praxisIcon]=\"starIcon(idx, tr2.value)\"\n [color]=\"ratingThemeColor(tr2)\"\n [style.cssText]=\"ratingIconStyle(tr2)\"\n ></mat-icon>\n }\n }\n @case (\"html\") {\n <span [innerHTML]=\"tr2.value\"></span>\n }\n @case (\"metric\") {\n <praxis-list-metric\n [metric]=\"tr2\"\n ></praxis-list-metric>\n }\n @case (\"compose\") {\n <praxis-list-compose\n [compose]=\"tr2\"\n ></praxis-list-compose>\n }\n @case (\"component\") {\n <praxis-list-runtime-component\n [component]=\"tr2\"\n ></praxis-list-runtime-component>\n }\n @default {\n <span>{{ tr2.value }}</span>\n }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n\n @if ((visibleActions(it, \"trailing\") || []).length) {\n <div\n class=\"tile-actions\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"onActionKeydown($event)\"\n (keydown.space)=\"onActionKeydown($event)\"\n >\n @for (\n action of visibleActions(it, \"trailing\");\n let aidx = $index;\n track action?.id ?? $index\n ) {\n @if ((action.kind || \"icon\") === \"icon\") {\n <button\n type=\"button\"\n [praxisIconButton]=\"action.icon || 'more_horiz'\"\n size=\"compact\"\n [busy]=\"isActionLoading(action.id, it, i)\"\n [style.cssText]=\"actionIconStyle(action.color)\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n ></button>\n } @else {\n @if (action.buttonVariant === \"stroked\") {\n <button\n mat-stroked-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'stroked')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (action.buttonVariant === \"raised\") {\n <button\n mat-raised-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n @if (\n !action.buttonVariant || action.buttonVariant === \"flat\"\n ) {\n <button\n mat-flat-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'flat')\"\n (click)=\"onActionClick($event, action.id, it, i)\"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, it, i)\"\n [ngClass]=\"{\n 'action-loading': isActionLoading(action.id, it, i),\n }\"\n >\n @if (isActionLoading(action.id, it, i)) {\n <mat-progress-spinner\n class=\"action-spinner\"\n mode=\"indeterminate\"\n diameter=\"16\"\n strokeWidth=\"3\"\n ></mat-progress-spinner>\n } @else {\n {{ action.label || action.id }}\n }\n </button>\n }\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Remote pagination stays attached to the collection footer. -->\n @if (isRemoteDataMode() && !(error$ | async)) {\n @if (page$ | async; as ps) {\n @if (total$ | async; as total) {\n @if (config.ui?.showRange === false) {\n <div class=\"list-paginator-total\" aria-live=\"polite\">\n {{ remoteTotalLabel(total) }}\n </div>\n }\n <mat-paginator\n [length]=\"total || 0\"\n [pageIndex]=\"ps.pageNumber || 0\"\n [pageSize]=\"ps.pageSize || config.layout?.pageSize || 10\"\n [pageSizeOptions]=\"listPageSizeOptions()\"\n [selectConfig]=\"paginatorSelectConfig\"\n [showFirstLastButtons]=\"true\"\n [class.hide-range]=\"config.ui?.showRange === false\"\n (page)=\"onPageChange($event)\"\n >\n </mat-paginator>\n }\n }\n }\n </ng-template>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block}.praxis-list-root{container-type:inline-size;--p-list-radius: var(--md-sys-shape-corner-medium, 16px);--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-blur: 10px;--p-list-surface: var(--md-sys-color-surface-container);--p-list-surface-low: var(--md-sys-color-surface);--p-list-surface-high: var( --md-sys-color-surface-container-high, var(--md-sys-color-surface-container) );--p-list-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-accent: var(--md-sys-color-primary);--p-list-accent-weak: var(--md-sys-color-primary-container);--p-list-item-surface: var( --md-sys-color-surface-container-low, var(--md-sys-color-surface) );--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--p-list-item-hover-surface: var(--md-sys-color-surface-container-low);--p-list-item-active-surface: var(--md-sys-color-surface-container);--p-list-item-selected-surface: var(--md-sys-color-surface-container);--p-list-grad-from: var(--md-sys-color-primary-container);--p-list-grad-to: var(--md-sys-color-tertiary-container);--p-list-grad-angle: 135deg;--p-list-grad-foreground: var( --md-sys-color-on-primary-container, var(--md-sys-color-on-surface) );--p-list-grad-foreground-muted: color-mix( in srgb, var(--p-list-grad-foreground) 76%, transparent );--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--p-list-trailing-max-width: 320px;--p-list-item-gap: 10px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 10px;--p-list-item-stack-gap: 0px;--p-list-meta-size: .875rem;--p-list-meta-weight: 500;--p-list-chip-height: 22px;--p-list-chip-font-size: 12px;--p-list-trailing-padding-right: 8px;--p-list-action-button-height: 32px;--p-list-tile-minW: 240px;--p-list-tile-gap: 12px;--p-list-tile-padding: 12px;--p-list-tile-radius: 12px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;--p-list-tile-hover-overlay: .04;--p-list-tile-press-overlay: .08;--p-list-tile-press-scale: .99}.list-assistant{display:flex;justify-content:flex-end;gap:8px;padding:4px 4px 8px}.action-loading{opacity:.65}.action-spinner{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}.action-loading .mat-mdc-button-touch-target,.action-loading .mdc-button__label{opacity:.7}.skin-elevated,.skin-outline,.skin-flat,.skin-neumorphism{--p-list-item-surface: var( --mdc-elevated-card-container-color, var(--p-list-surface) );--p-list-item-border: var(--p-list-border)}.skin-elevated .item-card,.skin-outline .item-card,.skin-flat .item-card,.skin-neumorphism .item-card{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:var(--p-list-radius);box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .item-tile,.skin-outline .item-tile,.skin-flat .item-tile,.skin-neumorphism .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));box-shadow:var(--p-list-shadow);border:var(--p-list-border)}.skin-elevated .mat-mdc-list-item .list-item-content,.skin-outline .mat-mdc-list-item .list-item-content,.skin-flat .mat-mdc-list-item .list-item-content,.skin-neumorphism .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * .75);box-shadow:var(--p-list-shadow);border:var(--p-list-item-border);color:var(--p-list-foreground)}.skin-outline{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline)}.skin-flat{--p-list-shadow: none;--p-list-border: 1px solid var(--md-sys-color-outline-variant)}.skin-neumorphism{--p-list-shadow: var(--md-sys-elevation-level2);--p-list-border: 1px solid var(--md-sys-color-outline-variant);--p-list-radius: 1.25rem}.skin-pill-soft .item-card,.skin-pill-soft .item-tile{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border)}.skin-pill-soft .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border-radius:calc(var(--p-list-radius) * 1.3);box-shadow:var(--md-sys-elevation-level1);border:var(--p-list-border);color:var(--p-list-foreground)}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted);--p-list-item-hover-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-active-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) );--p-list-item-selected-surface: linear-gradient( var(--p-list-grad-angle), var(--p-list-grad-from), var(--p-list-grad-to) )}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-gradient-tile .tile-media{background:color-mix(in srgb,var(--md-sys-color-surface) 74%,transparent);border-color:color-mix(in srgb,var(--p-list-foreground) 22%,transparent)}.skin-gradient-tile .tile-media mat-icon,.skin-gradient-tile .tile-meta,.skin-gradient-tile .tile-trailing,.skin-gradient-tile .feature,.skin-gradient-tile .secondary,.skin-gradient-tile .meta{color:var(--p-list-foreground-muted)}.skin-gradient-tile .tile-status,.skin-gradient-tile [data-rich-node-type=badge] .prx-rich-badge{color:var(--md-sys-color-on-secondary-container, var(--p-list-foreground));background:var(--md-sys-color-secondary-container, rgba(255, 255, 255, .72))}.skin-gradient-tile .mat-mdc-list-item .list-item-content{background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));border-radius:var(--p-list-radius);color:var(--p-list-foreground)}.skin-glass .item-card,.skin-glass .item-tile{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.skin-glass .mat-mdc-list-item .list-item-content{background:color-mix(in srgb,var(--md-sys-color-surface-container-low, rgba(255, 255, 255, .03)) 65%,transparent);border-radius:var(--p-list-radius);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 55%,transparent);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.density-compact .mat-mdc-list-item,.density-compact .item-card{--p-list-item-padding-y: 6px;--p-list-item-padding-x: 10px;--p-list-item-gap: 8px}.density-comfortable .mat-mdc-list-item,.density-comfortable .item-card{--p-list-item-padding-y: 8px;--p-list-item-padding-x: 12px;--p-list-item-gap: 10px}.praxis-list-root.lines-3 .mat-mdc-list-item{min-height:68px}.density-compact{--p-list-tile-gap: 10px;--p-list-tile-padding: 10px;--p-list-tile-minW: 188px}.density-comfortable{--p-list-tile-gap: 12px;--p-list-tile-padding: 12px}.item-spacing-none{--p-list-item-stack-gap: 0px}.item-spacing-tight{--p-list-item-stack-gap: 4px;--p-list-tile-gap: 10px}.item-spacing-default{--p-list-item-stack-gap: 6px;--p-list-tile-gap: 12px}.item-spacing-relaxed{--p-list-item-stack-gap: 14px;--p-list-tile-gap: 20px}.list-item-content{box-sizing:border-box;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),min(34vw,var(--p-list-trailing-max-width)));align-items:center;gap:var(--p-list-item-gap);padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x);width:100%;min-width:0;border-radius:calc(var(--p-list-radius) * .75);overflow:visible}.list-item-content--row-layout{--p-list-row-template-columns: var(--p-list-leading-width) minmax(0, 1fr) minmax(var(--p-list-trailing-min-width), max-content);--p-list-row-gap: var(--p-list-item-gap);--p-list-row-align-items: center;grid-template-columns:var(--p-list-row-template-columns);gap:var(--p-list-row-gap);align-items:var(--p-list-row-align-items);position:relative}.list-row-main-action{position:absolute;inset:0;z-index:1;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer}.list-row-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{position:relative;z-index:0;min-width:0;height:100%;align-self:stretch;display:flex;align-items:var(--p-list-row-slot-align-items, center);gap:8px}.list-item-content--row-layout :is(.list-row-slot--actions,.list-row-slot--expand,.list-row-slot--trailing){z-index:2}.list-item-content--row-layout .list-row-slot>praxis-rich-content,.list-item-content--row-layout .list-row-slot>praxis-list-metric,.list-item-content--row-layout .list-row-slot>praxis-list-compose,.list-item-content--row-layout .list-row-slot>praxis-list-runtime-component{min-width:0}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary,.list-row-slot--identity{min-width:0}.list-row-slot--identity>praxis-list-compose,.list-row-slot--primary>praxis-list-compose,.list-row-slot--secondary>praxis-list-compose{width:100%}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:nowrap;justify-content:flex-end;gap:8px}.list-row-slot .primary,.list-row-slot .secondary,.list-row-slot .meta,.list-row-slot .trailing{min-width:0}.list-item-main-action{grid-column:1/3;display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr);align-items:center;gap:var(--p-list-item-gap);min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.list-item-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:12px}.list-item-leading{display:flex;align-items:center;justify-content:center;min-width:0;min-height:100%}.list-item-leading>praxis-rich-content,.list-row-slot--leading>praxis-rich-content{min-width:0;max-width:100%}:host ::ng-deep .list-item-leading [data-rich-node-type=icon],:host ::ng-deep .list-row-slot--leading [data-rich-node-type=icon]{width:36px;height:36px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 14%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 28%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary, #06b6d4));box-sizing:border-box;flex-shrink:0}.leading-placeholder{width:24px;height:24px;display:inline-block}.list-item-text{min-width:0;display:grid;align-content:center;gap:2px}.list-item-trailing{box-sizing:border-box;min-width:0;width:100%;max-width:var(--p-list-trailing-max-width);display:flex;flex-wrap:nowrap;align-self:center;align-content:center;align-items:center;justify-content:end;gap:8px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-trailing>*{align-self:center}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{width:max-content;justify-self:end;align-self:center;display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap;max-width:100%;min-height:var(--p-list-action-button-height)}.list-item-actions .mat-mdc-button-base{min-height:var(--p-list-action-button-height);height:var(--p-list-action-button-height);display:inline-flex;align-items:center}.expand-toggle{color:var(--p-list-foreground-muted)}.mat-mdc-list-item .list-item-content{background:var(--p-list-item-surface);border:var(--p-list-item-border);transition:background .15s ease,box-shadow .15s ease,transform .15s ease}.mat-mdc-list-item{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-item.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-three-lines,.mat-mdc-list-item-single-line,.mat-mdc-list-item-two-line,.mat-mdc-list-item-three-line{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item{min-height:40px}.density-comfortable .mat-mdc-list-item{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text{display:block!important;width:100%!important;height:auto!important;padding:0!important;margin:0!important;overflow:visible!important;box-sizing:border-box}.mat-mdc-list-item{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list mat-list-item:not(:last-child),.praxis-list-root .mat-mdc-list-item:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:var(--p-list-radius, 12px);box-shadow:var(--p-list-shadow, 0 1px 3px rgba(0, 0, 0, .2))}.praxis-list-root[data-item-appearance=card] .mat-mdc-list-item:hover .list-item-content,.praxis-list-root.item-appearance-card .mat-mdc-list-item:hover .list-item-content{border-color:var(--md-sys-color-primary, #6750a4);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0, 0, 0, .25))}.praxis-list-root[data-item-appearance=capsule] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-capsule .mat-mdc-list-item .list-item-content{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:9999px;box-shadow:var(--p-list-shadow, none)}.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-item-content,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-item-content,.praxis-list-root[data-item-appearance=flat] .mat-mdc-list-item .list-row-shell--selectable,.praxis-list-root.item-appearance-flat .mat-mdc-list-item .list-row-shell--selectable{background:transparent;border:none;box-shadow:none;border-radius:0}.mat-mdc-list-item:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-shell{width:100%;min-width:0}.list-row-shell--selectable{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;border-radius:calc(var(--p-list-radius) * .75);background:var(--p-list-item-surface);border:var(--p-list-item-border);color:var(--p-list-foreground);overflow:hidden;transition:background .15s ease,box-shadow .15s ease,border-color .15s ease}.list-row-shell--selectable.list-row-shell--with-control{grid-template-columns:minmax(0,1fr) auto}.list-selection-control{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:center;padding:var(--p-list-item-padding-y) var(--p-list-item-padding-x) var(--p-list-item-padding-y) 0}.list-selection-control mat-radio-button{--mat-radio-selected-icon-color: var(--p-list-foreground);--mat-radio-selected-hover-icon-color: var(--p-list-foreground);--mat-radio-selected-focus-icon-color: var(--p-list-foreground);--mat-radio-selected-pressed-icon-color: var(--p-list-foreground);--mat-radio-checked-ripple-color: var(--p-list-foreground)}.praxis-list-root .mat-mdc-list-item .list-row-shell--selectable .list-item-content{background:transparent;border:0;border-radius:0;box-shadow:none}.mat-mdc-list-item:hover .list-row-shell--selectable{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-row-shell--selectable{background:var(--p-list-item-active-surface)}.list-row-shell--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.skin-elevated .list-row-shell--selectable,.skin-outline .list-row-shell--selectable,.skin-flat .list-row-shell--selectable,.skin-neumorphism .list-row-shell--selectable{background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-item-border);box-shadow:var(--p-list-shadow)}.skin-pill-soft .list-row-shell--selectable{border-radius:calc(var(--p-list-radius) * 1.3);background:var(--mdc-elevated-card-container-color, var(--p-list-surface));border:var(--p-list-border);box-shadow:var(--md-sys-elevation-level1)}.skin-gradient-tile .list-row-shell--selectable{border-radius:var(--p-list-radius);background:linear-gradient(var(--p-list-grad-angle),var(--p-list-grad-from),var(--p-list-grad-to));color:var(--p-list-foreground)}.skin-glass .list-row-shell--selectable{border-radius:var(--p-list-radius);background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.executive-inline-skin{--p-list-leading-width: 56px;--p-list-trailing-min-width: 232px;--p-list-item-padding-x: 14px;--p-list-item-padding-y: 8px;--p-list-item-gap: 10px;--p-list-surface: #f8fafb;--p-list-surface-low: #ffffff;--p-list-item-surface: #ffffff;--p-list-item-hover-surface: #f7fafc;--p-list-item-active-surface: #eef4f8;--p-list-item-selected-surface: #eef4f8;--p-list-foreground: #17324d;--p-list-foreground-muted: #5b6f84;--p-list-chip-background: #eef4f8;--p-list-chip-color: #17324d;--p-list-chip-border-color: #d5e2ec;--md-sys-color-on-surface: #17324d;--md-sys-color-on-surface-variant: #5b6f84;--md-sys-color-surface: #ffffff;--md-sys-color-surface-container-low: #f1f5f9;--md-sys-color-surface-container: #e2e8f0;--md-sys-color-surface-container-high: #e2e8f0;--md-sys-color-surface-container-highest: #cbd5e1;--md-sys-color-outline: #94a3b8;--md-sys-color-outline-variant: #d5e2ec;--praxis-icon-btn-fg: #6d7f93;color:var(--p-list-foreground)}.executive-inline-skin .list-item-content--row-layout.exec-row-layout{min-height:72px;padding:12px 16px;background:linear-gradient(180deg,#fff,#fbfcfd)!important;border:1px solid #dce5ec!important;border-radius:18px;box-shadow:0 1px 2px #0f223a08,0 4px 14px #0f223a08!important;color:#17324d!important}.executive-inline-skin .mat-mdc-list-item:hover .list-item-content--row-layout.exec-row-layout{background:linear-gradient(180deg,#fff,#f7fafc)!important}.executive-inline-skin .list-item-content--row-layout.exec-row-layout+.item-expansion{margin-left:10px;margin-right:10px}.executive-inline-skin .list-item-content--row-layout.exec-row-layout .list-row-slot{min-height:34px}.executive-inline-skin .list-row-slot--leading{justify-content:center}.executive-inline-skin .list-row-slot--identity{align-items:center;padding-right:4px}.executive-inline-skin .list-row-slot--balance,.executive-inline-skin .list-row-slot--limit,.executive-inline-skin .list-row-slot--risk,.executive-inline-skin .list-row-slot--alerts{justify-content:center;padding-inline:2px}.executive-inline-skin .list-row-slot--owner{justify-content:flex-start;padding-left:0}.executive-inline-skin .list-row-slot--actions{justify-content:flex-end;padding-left:0}.executive-inline-skin .list-row-slot--expand{justify-content:center}:host ::ng-deep .executive-inline-skin .docs-expansion-leading{width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center;border-radius:15px;background:linear-gradient(180deg,#edf4f9,#e6eef5);color:#1b5f86;font-size:1rem;font-weight:800;letter-spacing:.02em;box-shadow:0 1px 3px #1b5f861f;border:1px solid #dbe7f0}:host ::ng-deep .executive-inline-skin .exec-balance-metric,:host ::ng-deep .executive-inline-skin .exec-limit-metric,:host ::ng-deep .executive-inline-skin .exec-risk-metric{min-width:0;gap:5px}:host ::ng-deep .executive-inline-skin .exec-balance-metric .p-list-metric__label,:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__label,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__label{font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#8090a1}:host ::ng-deep .executive-inline-skin .exec-balance-metric .p-list-metric__value,:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__value{font-size:.96rem;font-weight:800;letter-spacing:-.02em;color:#0d1f34;line-height:1.05}:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__caption{font-size:.66rem;font-weight:700;color:#8090a1}:host ::ng-deep .executive-inline-skin .exec-limit-metric .p-list-metric__progress{width:68px;justify-self:center;height:3px}:host ::ng-deep .executive-inline-skin .exec-risk-metric{min-width:84px;justify-items:center}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__main{gap:5px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__value{font-size:1.02rem;font-weight:800;letter-spacing:-.024em;line-height:1}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__progress{width:56px;justify-self:center;height:3px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__caption{font-size:.7rem;font-weight:700;line-height:1.1}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__below-progress,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__caption--below-progress{justify-self:center;margin-top:-1px}:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__icon mat-icon,:host ::ng-deep .executive-inline-skin .exec-risk-metric .p-list-metric__icon .prx-rich-icon{width:15px;height:15px;font-size:15px}.executive-inline-skin .list-item-actions{gap:6px;flex-wrap:nowrap}.executive-inline-skin .list-row-slot--actions .list-item-actions{justify-content:flex-end}.executive-inline-skin .list-item-actions button,.executive-inline-skin .expand-toggle{--praxis-icon-btn-fg: #6d7f93;width:30px;height:30px;min-width:30px;border-radius:12px;color:#6d7f93!important}.executive-inline-skin .list-item-actions button mat-icon,.executive-inline-skin .expand-toggle mat-icon{width:18px;height:18px;font-size:18px}.executive-inline-skin .item-expansion{position:relative;margin-top:-10px;padding:22px 26px;background:linear-gradient(180deg,#fcfdfe,#f5f8fb);border-color:#e4eaf0;border-radius:0 0 22px 22px;box-shadow:inset 0 1px #ffffffdb;color:var(--p-list-foreground)}.lead-image{position:relative;width:96px;height:72px;border-radius:12px;overflow:hidden}.lead-image img{width:100%;height:100%;object-fit:cover;display:block}.lead-image .lead-badge{position:absolute;left:8px;bottom:8px}.inline-image{position:relative;width:20px;height:20px;border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.inline-image img{width:100%;height:100%;object-fit:cover;display:block}.inline-image .inline-badge{position:absolute;left:2px;bottom:2px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-media .list-item-content{gap:16px}.model-media .item-card{--p-list-leading-width: 136px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.model-hotel .item-card{--p-list-leading-width: 160px}.primary,.secondary{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.primary{-webkit-line-clamp:1;font-weight:600;color:var(--p-list-foreground)}.secondary{-webkit-line-clamp:1;color:var(--p-list-foreground-muted)}.lines-3 .tertiary{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-tile .primary{-webkit-line-clamp:2;font-size:.95rem;line-height:1.25rem}.item-tile .secondary{-webkit-line-clamp:2;font-size:.8rem;line-height:1.1rem}.tertiary{color:var(--p-list-foreground-muted)}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:inherit}.feature{display:inline-flex;align-items:center;gap:6px}.feature-line{display:block}.feature-progress{display:block;width:88px;height:4px;margin-top:6px;border-radius:999px;background:#dbe5eb;overflow:hidden}.feature-progress__value{display:block;height:100%;border-radius:inherit;background:#2f9b69}.meta{color:var(--p-list-foreground);font-size:var(--p-list-meta-size);font-weight:var(--p-list-meta-weight);font-variant-numeric:tabular-nums;max-width:100%;min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta>span,.meta praxis-rich-content{min-width:0;display:inline-flex;align-items:center;justify-content:flex-end;gap:4px;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta .mat-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;line-height:1;vertical-align:middle}.trailing{color:var(--p-list-foreground-muted);margin-left:0;max-width:100%;min-width:0;display:inline-flex;justify-content:flex-end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trailing praxis-rich-content{min-width:0}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge],:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}:host ::ng-deep .meta praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .trailing praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge,:host ::ng-deep .list-row-slot praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:2px 10px;border-radius:999px;font-size:.72rem;font-weight:600;letter-spacing:.02em;border:1px solid var(--p-list-chip-border-color, transparent);background:var(--p-list-chip-background, var(--md-sys-color-primary-container, #e8def8));color:var(--p-list-chip-color, var(--md-sys-color-on-primary-container, #21005d));line-height:18px}.section-header{display:block;font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.section-header praxis-rich-content{display:block;width:100%}.section-header--setup{margin:8px 12px 12px;padding:14px 16px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:color-mix(in srgb,var(--p-list-surface) 92%,var(--md-sys-color-primary) 8%);color:var(--p-list-foreground);font-weight:500}praxis-empty-state-card.section-header,praxis-empty-state-card.section-header--setup{margin:0;padding:0;border:0;border-radius:0;background:transparent;font-size:inherit;font-weight:inherit}.praxis-list-root mat-list{display:block;padding-bottom:12px}.praxis-list-root .mat-divider{margin-left:var(--p-list-item-padding-x);margin-right:var(--p-list-item-padding-x)}.item-expansion{margin:0 var(--p-list-item-padding-x) var(--p-list-item-stack-gap);padding:var(--p-list-expansion-padding, 14px 16px);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75);color:var(--p-list-foreground);white-space:normal;min-width:0}.praxis-list-root[data-item-appearance=card] .list-row-shell--expanded .list-item-content,.praxis-list-root.item-appearance-card .list-row-shell--expanded .list-item-content{border-bottom-left-radius:0;border-bottom-right-radius:0}.praxis-list-root[data-item-appearance=card] .item-expansion--attached,.praxis-list-root.item-appearance-card .item-expansion--attached{margin:0;border-top:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--p-list-radius, 12px);border-bottom-right-radius:var(--p-list-radius, 12px);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--p-list-surface)) 82%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 65%,transparent)}.skin-glass .item-expansion--attached{backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur))}.item-expansion--detached,.item-expansion--modal{margin-top:var(--p-list-item-stack-gap);background:var(--md-sys-color-surface-container, var(--p-list-surface));box-shadow:var(--md-sys-elevation-level1)}.item-expansion--modal{border-color:var(--md-sys-color-outline);box-shadow:var(--md-sys-elevation-level3)}.item-expansion-grid{display:grid;grid-template-columns:var(--p-list-expansion-columns, repeat(auto-fit, minmax(220px, 1fr)));gap:var(--p-list-expansion-gap, 16px)}.expansion-section{min-width:0;display:grid;gap:10px;align-content:start}.expansion-section-title{font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-info-list,.expansion-timeline,.expansion-key-value{display:grid;gap:10px}.expansion-info-item,.expansion-timeline-item{display:grid;gap:4px;min-width:0;padding:10px 12px;border-radius:14px;background:var(--p-list-item-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent 28%)}.expansion-info-title,.expansion-timeline-title{font-size:.92rem;font-weight:600;color:var(--p-list-foreground);white-space:normal;overflow-wrap:break-word}.expansion-info-value,.expansion-timeline-meta,.expansion-timeline-description,.expansion-empty{font-size:.82rem;line-height:1.45;color:var(--p-list-foreground-muted);white-space:normal;overflow-wrap:break-word}.expansion-chip-list{display:flex;flex-wrap:wrap;gap:8px}.expansion-chip{background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant)}.expansion-key-value{margin:0;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 12px}.expansion-key-value-row{display:grid;align-content:start;gap:3px;min-width:0;overflow:hidden;padding:8px 10px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest, rgba(255, 255, 255, .04)) 45%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12)) 45%,transparent)}.expansion-key-value-row dt,.expansion-key-value-row dd{margin:0;min-width:0;white-space:normal;overflow-wrap:break-word}.expansion-key-value-row dt{font-size:.68rem;font-weight:700;line-height:1.25;letter-spacing:.05em;text-transform:uppercase;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.85rem;font-weight:600;line-height:1.35;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, max(300px, var(--p-list-tile-minW)))), 1fr)));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:var(--p-list-card-grid-columns, repeat(auto-fit, minmax(min(100%, var(--p-list-card-minW, var(--p-list-tile-minW))), 1fr)));gap:var(--p-list-tile-gap)}.item-tile{position:relative;display:flex;flex-direction:column;gap:10px;padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);background:var(--p-list-surface);border:var(--p-list-border);color:var(--p-list-foreground);cursor:pointer;min-height:160px;transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out}.item-tile:hover{box-shadow:var(--md-sys-elevation-level2);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-tile:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.tile-main-action{display:flex;flex:1;min-width:0;flex-direction:column;gap:10px;color:inherit;cursor:pointer}.tile-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--p-list-item-surface);border:1px solid var(--md-sys-color-outline-variant);display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover;display:block}.tile-media mat-icon{font-size:28px;height:28px;width:28px;color:var(--p-list-foreground-muted)}.tile-body{display:grid;gap:6px;min-width:0}.tile-meta{display:inline-flex;align-items:center;gap:6px;font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile-trailing{font-size:.75rem;color:var(--p-list-foreground-muted);white-space:nowrap}.tiles-features{display:flex;flex-wrap:wrap;gap:8px;color:inherit}.tile-status{position:absolute;top:10px;right:10px}.tile-actions{position:absolute;top:8px;left:8px;display:flex;gap:4px;opacity:0;pointer-events:none;transform:translateY(-2px);transition:opacity .16s ease-out,transform .16s ease-out}.item-tile:hover .tile-actions,.item-tile:focus-within .tile-actions{opacity:1;pointer-events:auto;transform:translateY(0)}@media(hover:none){.tile-actions{opacity:1;pointer-events:auto;transform:none}}@media(max-width:600px){.tiles-grid,.cards-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}@media(prefers-reduced-motion:reduce){.item-tile,.tile-actions{transition:none}.item-tile:active{transform:none}.item-card{transition:none}.item-card:active{transform:none}}.item-card{padding:max(var(--p-list-tile-padding),16px);display:flex;flex-direction:column;gap:var(--p-list-item-gap);min-height:var(--p-list-card-minH, 220px);position:relative;cursor:pointer;background:var(--p-list-surface);border:var(--p-list-border);border-radius:var(--p-list-tile-radius);box-shadow:var(--p-list-shadow);transition:box-shadow .16s ease-out,border-color .16s ease-out,transform .12s ease-out,background .16s ease-out;--p-list-leading-width: 96px;--p-list-trailing-min-width: 0px}.density-compact .item-card{min-height:var(--p-list-card-minH, 148px)}.pdx-list-item--primary{--p-list-item-rule-tone: var(--md-sys-color-primary, #06b6d4);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 52%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--success{--p-list-item-rule-tone: var(--p-color-success, #10b981);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 48%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 9%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--warning{--p-list-item-rule-tone: var( --p-color-warning, var(--md-sys-color-tertiary, #f59e0b) );border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 54%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 10%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--danger{--p-list-item-rule-tone: var(--md-sys-color-error, #ef4444);border-color:color-mix(in srgb,var(--p-list-item-rule-tone) 56%,var(--md-sys-color-outline-variant))!important;background:color-mix(in srgb,var(--p-list-item-rule-tone) 11%,var(--p-list-item-surface, var(--p-list-surface)))!important;box-shadow:inset 3px 0 0 var(--p-list-item-rule-tone)!important}.pdx-list-item--muted{opacity:.78;border-style:dashed!important;background:color-mix(in srgb,var(--md-sys-color-surface-variant) 34%,var(--p-list-surface))!important}.pdx-list-item--neutral{border-color:var(--md-sys-color-outline-variant)!important;background:var(--p-list-surface)!important}.card-main-action{display:block;width:100%;min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.card-main-action:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px;border-radius:calc(var(--p-list-tile-radius) - 4px)}.item-card .list-item-content{display:block;padding:0;min-width:0;overflow:hidden}.item-card .list-item-leading{position:absolute;top:18px;left:18px;min-height:0;z-index:1}.item-card .leading-placeholder{width:36px;height:36px}.item-card .leading-icon.mat-icon,.item-card .list-item-leading>mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent));color:var(--md-sys-color-primary)}.item-card .list-item-text{display:grid;gap:9px;padding-left:50px;width:100%;min-width:0;box-sizing:border-box}.item-card .primary{padding-right:min(50%,160px);font-size:1rem;font-weight:800;letter-spacing:-.01em;line-height:1.18;min-width:0;overflow-wrap:anywhere}.item-card .secondary{color:var(--p-list-foreground-muted);font-weight:600;line-height:1.35;min-width:0;overflow-wrap:anywhere}.item-card .features{display:flex;flex-direction:column;gap:8px;margin-top:2px}.item-card .feature{display:inline-flex;align-items:start;gap:8px;min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .feature mat-icon{margin-top:1px;color:var(--p-list-foreground-muted);opacity:.86}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width);grid-column:1/-1;align-items:stretch;padding-right:0}.card-detail-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px;margin-top:16px}.card-detail{min-width:0;padding:11px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 22%,transparent),color-mix(in srgb,var(--p-list-surface) 92%,transparent));box-shadow:inset 0 1px #ffffff14}.card-detail__label{display:block;margin-bottom:3px;color:var(--p-list-foreground-muted);font-size:.68rem;font-weight:700;letter-spacing:.08em;line-height:1.1;text-transform:uppercase}.card-detail__value{display:block;min-width:0;color:var(--p-list-foreground);font-size:.94rem;font-weight:800;line-height:1.2;overflow-wrap:normal;word-break:normal}.card-detail__value,.card-detail__value *{white-space:nowrap}.card-detail--balance .card-detail__value{color:var(--md-sys-color-primary)}.card-detail--limit .card-detail__value{color:var(--md-sys-color-error)}.card-detail--risk .card-detail__value{color:var(--md-sys-color-tertiary, var(--p-list-foreground))}.item-card:hover{box-shadow:var(--md-sys-elevation-level3);border-color:var(--md-sys-color-outline-variant);background:var(--p-list-item-hover-surface)}.item-card:active{transform:scale(var(--p-list-tile-press-scale));background:var(--p-list-item-active-surface)}.card-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:6px 8px 4px;border-top:1px solid var(--md-sys-color-outline-variant);margin-top:auto}.status-overlay{position:absolute;top:14px;right:14px;max-width:min(42%,148px);overflow:hidden;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto;width:100%;min-width:0;max-width:100%}.status-overlay .mdc-evolution-chip__text-label,.status-overlay .mat-mdc-chip-action-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.leading-icon.mat-icon,.list-item-leading>mat-icon,.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon],[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon]{width:36px;height:36px;min-width:36px;line-height:36px;font-size:19px;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;box-sizing:border-box;background:var(--p-list-leading-icon-bg, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 15%, transparent));border:1px solid var(--p-list-leading-icon-border, color-mix(in srgb, var(--md-sys-color-primary, #06b6d4) 30%, transparent));color:var(--p-list-leading-icon-color, var(--md-sys-color-primary));box-shadow:inset 0 1px #ffffff0f}.list-item-leading ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon,[data-row-slot=leading] ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=icon] .prx-rich-icon{font-size:19px;width:19px;height:19px;line-height:19px;color:inherit}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);--mdc-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mat-chip-elevated-container-color: var( --p-list-chip-background, var(--md-sys-color-surface-container-high) );--mdc-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );--mat-chip-label-text-color: var( --p-list-chip-color, var(--md-sys-color-on-surface) );--mdc-chip-outline-color: var(--p-list-chip-border-color, transparent);--mat-chip-outline-color: var(--p-list-chip-border-color, transparent);font-size:var(--p-list-chip-font-size);font-weight:600;letter-spacing:.02em;border-radius:999px!important;background-color:var(--p-list-chip-background, var(--md-sys-color-surface-container-high))!important;color:var(--p-list-chip-color, var(--md-sys-color-on-surface))!important;border:1px solid var(--p-list-chip-border-color, transparent)!important}:host ::ng-deep .mat-mdc-chip .mdc-evolution-chip__text-label,:host ::ng-deep .mat-mdc-chip .mat-mdc-chip-action-label{color:var(--p-list-chip-color, inherit)!important;font-weight:600;font-size:.72rem;letter-spacing:.02em}.meta .mat-icon{font-size:18px;height:18px;width:18px}.features{overflow:hidden}@keyframes shimmer{0%{background-position:-468px 0}to{background-position:468px 0}}.skeleton{animation-duration:1.2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear;background:linear-gradient(to right,var(--md-sys-color-surface-container-low) 8%,var(--md-sys-color-surface-container) 18%,var(--md-sys-color-surface-container-low) 33%);background-size:800px 104px;position:relative}.skeleton-avatar{width:32px;height:32px;border-radius:50%}.skeleton-line{height:10px;margin:6px 0;border-radius:6px}.skeleton-chip{width:48px;height:18px;border-radius:999px}.chip-outlined.mat-mdc-chip{background-color:var(--p-list-chip-background, transparent)!important;border:1px solid var(--p-list-chip-border-color, currentColor)!important;color:var(--p-list-chip-color, currentColor)!important}.w-60{width:60%}.w-40{width:40%}.list-collection-toolbar{display:flex;align-items:center;gap:12px;padding:12px;margin-bottom:8px;color:var(--p-list-foreground);background:var(--p-list-surface-low);border:var(--p-list-border);border-radius:calc(var(--p-list-radius) * .75)}.list-toolbar-search{flex:1 1 320px;min-width:220px;max-width:440px}.list-toolbar-commands{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;margin-inline-start:auto}.list-toolbar-commands button{border-radius:8px}.list-toolbar-commands button .mat-icon{margin-right:6px}.list-toolbar-sort{width:200px}.list-remote-error{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;margin:8px 4px 0;padding:16px;color:var(--md-sys-color-on-error-container);background:var(--md-sys-color-error-container);border-radius:calc(var(--p-list-radius) * .75)}.list-remote-error__copy{display:flex;flex-direction:column;gap:4px;min-width:0}.list-remote-error__copy span{color:color-mix(in srgb,var(--md-sys-color-on-error-container) 82%,transparent);line-height:1.45}.list-remote-error button{color:var(--md-sys-color-on-error-container);--mat-button-outlined-label-text-color: var( --md-sys-color-on-error-container );--mat-button-outlined-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent );--mdc-outlined-button-label-text-color: var( --md-sys-color-on-error-container );--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-on-error-container) 42%, transparent )}.mat-mdc-paginator{margin-top:14px;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--p-list-surface-low);color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-container{min-height:40px;padding:4px 8px;gap:6px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select{margin-left:8px;width:92px}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-text-field-wrapper{--mdc-outlined-text-field-container-color: color-mix( in srgb, var(--p-list-surface-low) 92%, var(--md-sys-color-on-surface) 8% );--mdc-outlined-text-field-input-text-color: var(--p-list-foreground);min-height:40px;padding-inline:12px 8px;background:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;background-color:color-mix(in srgb,var(--p-list-surface-low) 92%,var(--md-sys-color-on-surface) 8%)!important;color:var(--p-list-foreground)!important}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-form-field-infix{min-height:40px;padding-block:8px;width:auto}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-page-size-select .mat-mdc-select-trigger{min-height:24px;padding-right:2px;color:var(--p-list-foreground)}:host ::ng-deep .mat-mdc-paginator .mat-mdc-paginator-range-label,:host ::ng-deep .mat-mdc-paginator .mat-mdc-select-value-text{font-size:12px;color:var(--p-list-foreground-muted)}.list-paginator-total{margin-top:14px;padding:4px 8px 0;font-size:12px;color:var(--p-list-foreground-muted)}:host ::ng-deep .mat-mdc-paginator.hide-range .mat-mdc-paginator-range-label{display:none}::ng-deep .praxis-list-paginator-select-panel.mat-mdc-select-panel{--mat-select-panel-background-color: var( --md-sys-color-surface-container, var(--mat-sys-surface-container) );background:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;background-color:var(--md-sys-color-surface-container, var(--mat-sys-surface-container))!important;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #d7dbe5) 70%,transparent);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, #000) 28%,transparent)}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option{--mat-option-label-text-color: var(--md-sys-color-on-surface, #111827);color:var(--md-sys-color-on-surface, #111827)!important}::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .praxis-list-paginator-select-panel .mat-mdc-option.mat-mdc-option-active{--mat-option-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-primary, #2f7cff) 14%, transparent );background:color-mix(in srgb,var(--md-sys-color-primary, #2f7cff) 14%,transparent)!important;color:var(--md-sys-color-on-surface, #111827)!important}.muted{color:var(--p-list-foreground-muted)}@container (max-width: 720px){.executive-inline-skin .list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.executive-inline-skin .list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--primary,.executive-inline-skin .list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.executive-inline-skin .list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.executive-inline-skin .list-item-content--row-layout .list-row-slot--meta,.executive-inline-skin .list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.executive-inline-skin .list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.executive-inline-skin .list-selection-control{padding-left:0}.executive-inline-skin .list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.executive-inline-skin .list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.executive-inline-skin .list-item-trailing .list-item-actions{margin-inline-start:auto}.executive-inline-skin .item-expansion{margin-left:0;margin-right:0}.executive-inline-skin .list-collection-toolbar{flex-direction:column;align-items:stretch}.executive-inline-skin .list-toolbar-search,.executive-inline-skin .list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.executive-inline-skin .list-toolbar-commands{width:100%;margin-inline-start:0}.executive-inline-skin .list-toolbar-sort{flex:1 1 100%}.executive-inline-skin .list-toolbar-commands button{flex:0 0 auto}.executive-inline-skin .list-remote-error{grid-template-columns:auto minmax(0,1fr)}.executive-inline-skin .list-remote-error button{grid-column:1/-1;justify-self:stretch}}@container (max-width: 420px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}@media(max-width:640px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-content--row-layout{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) max-content;grid-auto-flow:row;align-items:start}.list-item-content--row-layout .list-row-slot--leading{grid-column:1;grid-row:1}.list-item-content--row-layout .list-row-slot--primary,.list-item-content--row-layout .list-row-slot--identity{grid-column:2/-1;grid-row:1}.list-item-content--row-layout .list-row-slot--secondary{grid-column:2/-1;grid-row:2}.list-item-content--row-layout :is(.list-row-slot--primary,.list-row-slot--secondary){white-space:normal;overflow-wrap:anywhere}.list-item-content--row-layout .list-row-slot--meta,.list-item-content--row-layout .list-row-slot--risk{grid-column:2;grid-row:3;justify-content:flex-start}.list-item-content--row-layout .list-row-slot--trailing{grid-column:3;grid-row:3;justify-content:flex-end}.list-selection-control{padding-left:0}.list-item-content--row-layout :is(.list-row-slot--balance,.list-row-slot--limit,.list-row-slot--alerts,.list-row-slot--owner,.list-row-slot--actions,.list-row-slot--expand){grid-column:1/-1}.list-item-trailing{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:flex-start;padding-right:0;align-items:center;text-align:start;max-width:none;width:100%;gap:8px}.list-item-trailing .list-item-actions{margin-inline-start:auto}.item-expansion{margin-left:0;margin-right:0}.list-collection-toolbar{flex-direction:column;align-items:stretch}.list-toolbar-search,.list-toolbar-sort{flex:0 0 auto;width:100%;max-width:none;min-width:0}.list-toolbar-commands{width:100%;margin-inline-start:0}.list-toolbar-sort{flex:1 1 100%}.list-toolbar-commands button{flex:0 0 auto}.list-remote-error{grid-template-columns:auto minmax(0,1fr)}.list-remote-error button{grid-column:1/-1;justify-self:stretch}}.list-loading-status{display:flex;align-items:center;gap:8px;padding:12px 0;color:inherit;--mat-progress-spinner-active-indicator-color: currentColor}.list-loading-status:empty{display:none}.praxis-list-virtual-viewport,.praxis-list-bounded-viewport{display:block;width:100%;overflow-y:auto;outline:none;padding-right:4px;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent) transparent}.praxis-list-virtual-viewport::-webkit-scrollbar,.praxis-list-bounded-viewport::-webkit-scrollbar{width:6px;height:6px}.praxis-list-virtual-viewport::-webkit-scrollbar-track,.praxis-list-bounded-viewport::-webkit-scrollbar-track{background:transparent}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--md-sys-color-outline-variant, #64748b) 55%,transparent);border-radius:999px}.praxis-list-virtual-viewport::-webkit-scrollbar-thumb:hover,.praxis-list-bounded-viewport::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, #94a3b8) 72%,transparent)}.praxis-list-virtual-viewport{height:var(--p-list-viewport-height, 400px);contain:strict}.praxis-list-virtual-viewport .praxis-list-virtual-list{padding-top:0;padding-bottom:0}.list-item-menu-trigger{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--md-sys-shape-corner-full, 9999px);color:var(--p-list-foreground-muted, inherit);transition:background-color .15s ease,color .15s ease}.list-item-menu-trigger:hover{background-color:var(--p-list-item-hover-surface, rgba(0, 0, 0, .04));color:var(--p-list-foreground, inherit)}\n"] }]
|
|
12912
13397
|
}], propDecorators: { config: [{
|
|
12913
13398
|
type: Input
|
|
12914
13399
|
}], listId: [{
|
|
@@ -12937,7 +13422,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
12937
13422
|
type: Output
|
|
12938
13423
|
}], exportAction: [{
|
|
12939
13424
|
type: Output
|
|
12940
|
-
}], configPatchChange: [{ type: i0.Output, args: ["configPatchChange"] }]
|
|
13425
|
+
}], configPatchChange: [{ type: i0.Output, args: ["configPatchChange"] }], searchInputRef: [{
|
|
13426
|
+
type: ViewChild,
|
|
13427
|
+
args: ['searchInput']
|
|
13428
|
+
}] } });
|
|
12941
13429
|
|
|
12942
13430
|
class PraxisListSkinPreviewComponent {
|
|
12943
13431
|
skin;
|
|
@@ -13988,17 +14476,66 @@ class PraxisListConfigEditor {
|
|
|
13988
14476
|
if (!name)
|
|
13989
14477
|
continue;
|
|
13990
14478
|
names.push(name);
|
|
14479
|
+
const type = f.type ? f.type.trim() : undefined;
|
|
14480
|
+
const domainMeta = this.extractFieldDomainMeta(f, type);
|
|
13991
14481
|
nextMeta[name] = {
|
|
13992
14482
|
name,
|
|
13993
14483
|
...(f.label ? { label: f.label.trim() } : {}),
|
|
13994
|
-
...(
|
|
14484
|
+
...(type ? { type } : {}),
|
|
13995
14485
|
...(f.description ? { description: f.description.trim() } : {}),
|
|
14486
|
+
...(domainMeta.enumValues?.length ? { enumValues: domainMeta.enumValues } : {}),
|
|
14487
|
+
...(domainMeta.optionLabels ? { optionLabels: domainMeta.optionLabels } : {}),
|
|
13996
14488
|
};
|
|
13997
14489
|
}
|
|
13998
14490
|
this.fieldMetaByName = nextMeta;
|
|
13999
14491
|
this.fields = names;
|
|
14000
14492
|
}
|
|
14001
14493
|
}
|
|
14494
|
+
extractFieldDomainMeta(rawField, fallbackType) {
|
|
14495
|
+
if (!rawField || typeof rawField !== 'object') {
|
|
14496
|
+
return {};
|
|
14497
|
+
}
|
|
14498
|
+
const f = rawField;
|
|
14499
|
+
const rawOptions = f['enumValues'] ??
|
|
14500
|
+
f['enum'] ??
|
|
14501
|
+
f['options'] ??
|
|
14502
|
+
(f['uiConfig'] && typeof f['uiConfig'] === 'object'
|
|
14503
|
+
? f['uiConfig']['options']
|
|
14504
|
+
: undefined);
|
|
14505
|
+
const enumValues = [];
|
|
14506
|
+
const seen = new Set();
|
|
14507
|
+
const optionLabels = {};
|
|
14508
|
+
if (Array.isArray(rawOptions)) {
|
|
14509
|
+
for (const item of rawOptions) {
|
|
14510
|
+
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
|
14511
|
+
const key = String(item).trim();
|
|
14512
|
+
if (key && !seen.has(key)) {
|
|
14513
|
+
seen.add(key);
|
|
14514
|
+
enumValues.push(key);
|
|
14515
|
+
}
|
|
14516
|
+
}
|
|
14517
|
+
else if (item && typeof item === 'object') {
|
|
14518
|
+
const rec = item;
|
|
14519
|
+
const key = String(rec['value'] ?? rec['key'] ?? rec['id'] ?? rec['code'] ?? '').trim();
|
|
14520
|
+
const label = String(rec['label'] ?? rec['text'] ?? rec['description'] ?? '').trim();
|
|
14521
|
+
if (key && !seen.has(key)) {
|
|
14522
|
+
seen.add(key);
|
|
14523
|
+
enumValues.push(key);
|
|
14524
|
+
}
|
|
14525
|
+
if (key && label && label !== key) {
|
|
14526
|
+
optionLabels[key] = label;
|
|
14527
|
+
}
|
|
14528
|
+
}
|
|
14529
|
+
}
|
|
14530
|
+
}
|
|
14531
|
+
if (enumValues.length === 0 && String(fallbackType || '').trim().toLowerCase() === 'boolean') {
|
|
14532
|
+
enumValues.push('true', 'false');
|
|
14533
|
+
}
|
|
14534
|
+
return {
|
|
14535
|
+
...(enumValues.length > 0 ? { enumValues } : {}),
|
|
14536
|
+
...(Object.keys(optionLabels).length > 0 ? { optionLabels } : {}),
|
|
14537
|
+
};
|
|
14538
|
+
}
|
|
14002
14539
|
getFieldLabel(fieldName) {
|
|
14003
14540
|
const key = String(fieldName ?? '').trim();
|
|
14004
14541
|
if (!key)
|
|
@@ -14332,6 +14869,11 @@ class PraxisListConfigEditor {
|
|
|
14332
14869
|
});
|
|
14333
14870
|
this.document = document;
|
|
14334
14871
|
this.working = document.config;
|
|
14872
|
+
this.lastNonEmptyResourcePath = String(this.working?.dataSource?.resourcePath ?? '')
|
|
14873
|
+
.trim()
|
|
14874
|
+
.replace(/^\/+|\/+$/g, '')
|
|
14875
|
+
.replace(/^api\//i, '')
|
|
14876
|
+
.toLowerCase();
|
|
14335
14877
|
this.resetVisualMappingState();
|
|
14336
14878
|
this.hydrateMappingFromTemplating(this.working.templating);
|
|
14337
14879
|
this.hydrateUiEditorFromConfig();
|
|
@@ -14493,11 +15035,19 @@ class PraxisListConfigEditor {
|
|
|
14493
15035
|
f?.hint ||
|
|
14494
15036
|
cat?.description ||
|
|
14495
15037
|
'').trim();
|
|
15038
|
+
const primaryDomain = this.extractFieldDomainMeta(f, type);
|
|
15039
|
+
const fallbackDomain = !primaryDomain.enumValues?.length && cat
|
|
15040
|
+
? this.extractFieldDomainMeta(cat, type)
|
|
15041
|
+
: undefined;
|
|
15042
|
+
const enumValues = primaryDomain.enumValues ?? fallbackDomain?.enumValues;
|
|
15043
|
+
const optionLabels = primaryDomain.optionLabels ?? fallbackDomain?.optionLabels;
|
|
14496
15044
|
nextMeta[name] = {
|
|
14497
15045
|
name,
|
|
14498
15046
|
...(label ? { label } : {}),
|
|
14499
15047
|
...(type ? { type } : {}),
|
|
14500
15048
|
...(description ? { description } : {}),
|
|
15049
|
+
...(enumValues?.length ? { enumValues } : {}),
|
|
15050
|
+
...(optionLabels ? { optionLabels } : {}),
|
|
14501
15051
|
};
|
|
14502
15052
|
}
|
|
14503
15053
|
this.fieldMetaByName = nextMeta;
|
|
@@ -14538,9 +15088,30 @@ class PraxisListConfigEditor {
|
|
|
14538
15088
|
]
|
|
14539
15089
|
.map((field) => String(field ?? '').trim())
|
|
14540
15090
|
.filter(Boolean);
|
|
14541
|
-
|
|
15091
|
+
if (mappedDataFields.some((field) => !validFields.has(field))) {
|
|
15092
|
+
return true;
|
|
15093
|
+
}
|
|
15094
|
+
const templateRefs = new Set();
|
|
15095
|
+
const collectRefs = (val) => {
|
|
15096
|
+
if (typeof val === 'string') {
|
|
15097
|
+
for (const match of val.matchAll(/\$\{item\.([A-Za-z_][\w]*)(?:\|[^}]*)?\}/g)) {
|
|
15098
|
+
templateRefs.add(match[1]);
|
|
15099
|
+
}
|
|
15100
|
+
return;
|
|
15101
|
+
}
|
|
15102
|
+
if (!val || typeof val !== 'object')
|
|
15103
|
+
return;
|
|
15104
|
+
if (Array.isArray(val)) {
|
|
15105
|
+
val.forEach(collectRefs);
|
|
15106
|
+
return;
|
|
15107
|
+
}
|
|
15108
|
+
Object.values(val).forEach(collectRefs);
|
|
15109
|
+
};
|
|
15110
|
+
collectRefs(this.working?.templating);
|
|
15111
|
+
return Array.from(templateRefs).some((field) => !validFields.has(field));
|
|
14542
15112
|
}
|
|
14543
15113
|
pendingRemoteSlotInference = false;
|
|
15114
|
+
lastNonEmptyResourcePath = '';
|
|
14544
15115
|
syncSchemaFieldsFromWorking(immediate = false) {
|
|
14545
15116
|
const resourcePath = this.getActiveDataSourceMode() === 'remote'
|
|
14546
15117
|
? String(this.working?.dataSource?.resourcePath || '').trim()
|
|
@@ -14566,9 +15137,33 @@ class PraxisListConfigEditor {
|
|
|
14566
15137
|
});
|
|
14567
15138
|
}
|
|
14568
15139
|
onResourcePathChange(value) {
|
|
15140
|
+
const prevNormalized = this.lastNonEmptyResourcePath;
|
|
15141
|
+
const nextNormalized = String(value ?? '')
|
|
15142
|
+
.trim()
|
|
15143
|
+
.replace(/^\/+|\/+$/g, '')
|
|
15144
|
+
.replace(/^api\//i, '')
|
|
15145
|
+
.toLowerCase();
|
|
14569
15146
|
if (this.working?.dataSource) {
|
|
14570
15147
|
this.working.dataSource.resourcePath = value;
|
|
14571
15148
|
}
|
|
15149
|
+
if (nextNormalized.length === 0) {
|
|
15150
|
+
this.fields = [];
|
|
15151
|
+
this.fieldMetaByName = {};
|
|
15152
|
+
}
|
|
15153
|
+
else if (prevNormalized !== nextNormalized) {
|
|
15154
|
+
this.lastNonEmptyResourcePath = nextNormalized;
|
|
15155
|
+
if (prevNormalized.length > 0) {
|
|
15156
|
+
this.fields = [];
|
|
15157
|
+
this.fieldMetaByName = {};
|
|
15158
|
+
if (this.working?.dataSource) {
|
|
15159
|
+
delete this.working.dataSource.query;
|
|
15160
|
+
delete this.working.dataSource.sort;
|
|
15161
|
+
}
|
|
15162
|
+
this.queryJson = '';
|
|
15163
|
+
this.queryError = '';
|
|
15164
|
+
this.sortField = undefined;
|
|
15165
|
+
}
|
|
15166
|
+
}
|
|
14572
15167
|
this.resourcePathChanges.next({
|
|
14573
15168
|
path: String(value ?? '').trim(),
|
|
14574
15169
|
immediate: false,
|
|
@@ -14872,7 +15467,74 @@ class PraxisListConfigEditor {
|
|
|
14872
15467
|
target.locale = locale;
|
|
14873
15468
|
this.onMappingChanged();
|
|
14874
15469
|
}
|
|
15470
|
+
resolveStatusDomainField(explicitField) {
|
|
15471
|
+
if (this.getActiveDataSourceMode() === 'local') {
|
|
15472
|
+
return undefined;
|
|
15473
|
+
}
|
|
15474
|
+
const candidates = [
|
|
15475
|
+
explicitField,
|
|
15476
|
+
this.mappingTrailing?.field,
|
|
15477
|
+
this.mappingMeta?.type === 'chip' || this.mappingMeta?.type === 'icon'
|
|
15478
|
+
? this.mappingMeta?.field
|
|
15479
|
+
: undefined,
|
|
15480
|
+
this.mappingLeading?.type === 'chip' || this.mappingLeading?.type === 'icon'
|
|
15481
|
+
? this.mappingLeading?.field
|
|
15482
|
+
: undefined,
|
|
15483
|
+
]
|
|
15484
|
+
.map((f) => String(f ?? '').trim())
|
|
15485
|
+
.filter(Boolean);
|
|
15486
|
+
for (const candidate of candidates) {
|
|
15487
|
+
if (this.fieldMetaByName[candidate]?.enumValues?.length) {
|
|
15488
|
+
return candidate;
|
|
15489
|
+
}
|
|
15490
|
+
}
|
|
15491
|
+
const statusPattern = /(status|situacao|state|ativo|active|fase|etapa|stage|prioridade|priority|risco|risk|severidade|severity)/i;
|
|
15492
|
+
return this.fields.find((f) => statusPattern.test(f) && !!this.fieldMetaByName[f]?.enumValues?.length);
|
|
15493
|
+
}
|
|
15494
|
+
inferSemanticStatusColor(value, index) {
|
|
15495
|
+
const normalized = String(value ?? '')
|
|
15496
|
+
.normalize('NFD')
|
|
15497
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
15498
|
+
.trim()
|
|
15499
|
+
.toLowerCase();
|
|
15500
|
+
if (/^(falhou|failed|erro|error|critico|critical|inativo|inactive|cancelad[oa]|cancelled|canceled|rejeitad[oa]|rejected|bloquead[oa]|blocked|atrasad[oa]|overdue|vencid[oa]|expired|suspens[oa]|suspended|indisponivel|unavailable|alto|high|danger|false|nao|no)$/.test(normalized)) {
|
|
15501
|
+
return 'warn';
|
|
15502
|
+
}
|
|
15503
|
+
if (/^(em_andamento|in_progress|pendente|pending|pausad[oa]|paused|atencao|warning|aguardando|waiting|em_analise|review|processando|processing|rascunho|draft|medio|medium|parcial|partial|ultimas\s*vagas|last\s*spots)$/.test(normalized)) {
|
|
15504
|
+
return 'accent';
|
|
15505
|
+
}
|
|
15506
|
+
if (/^(ativo|active|concluid[oa]|completed|done|aprovad[oa]|approved|planejad[oa]|planned|disponivel|available|aberto|open|ok|normal|baixo|low|sucesso|success|true|sim|yes)$/.test(normalized)) {
|
|
15507
|
+
return 'primary';
|
|
15508
|
+
}
|
|
15509
|
+
const cycle = ['primary', 'accent', 'warn'];
|
|
15510
|
+
return cycle[index % cycle.length];
|
|
15511
|
+
}
|
|
15512
|
+
resolveDomainColorMapEntries(explicitField) {
|
|
15513
|
+
const field = this.resolveStatusDomainField(explicitField);
|
|
15514
|
+
const values = field ? this.fieldMetaByName[field]?.enumValues : undefined;
|
|
15515
|
+
if (!values?.length) {
|
|
15516
|
+
return [];
|
|
15517
|
+
}
|
|
15518
|
+
return values.map((key, index) => ({
|
|
15519
|
+
key,
|
|
15520
|
+
color: this.inferSemanticStatusColor(key, index),
|
|
15521
|
+
}));
|
|
15522
|
+
}
|
|
15523
|
+
resolveDomainLabelMapEntries(explicitField) {
|
|
15524
|
+
const field = this.resolveStatusDomainField(explicitField);
|
|
15525
|
+
const labels = field ? this.fieldMetaByName[field]?.optionLabels : undefined;
|
|
15526
|
+
if (!labels) {
|
|
15527
|
+
return [];
|
|
15528
|
+
}
|
|
15529
|
+
return Object.entries(labels)
|
|
15530
|
+
.filter(([key, label]) => !!key.trim() && !!label.trim())
|
|
15531
|
+
.map(([key, label]) => ({ key: key.trim(), label: label.trim() }));
|
|
15532
|
+
}
|
|
14875
15533
|
defaultStatusColorMapEntries() {
|
|
15534
|
+
const domainEntries = this.resolveDomainColorMapEntries();
|
|
15535
|
+
if (domainEntries.length > 0) {
|
|
15536
|
+
return domainEntries;
|
|
15537
|
+
}
|
|
14876
15538
|
const locale = this.defaultPresetLocale().toLowerCase();
|
|
14877
15539
|
if (locale.startsWith('pt')) {
|
|
14878
15540
|
return [
|
|
@@ -16178,6 +16840,19 @@ class PraxisListConfigEditor {
|
|
|
16178
16840
|
this.onMappingChanged();
|
|
16179
16841
|
}
|
|
16180
16842
|
applyStandardStatusColorMap() {
|
|
16843
|
+
const domainColors = this.resolveDomainColorMapEntries();
|
|
16844
|
+
if (domainColors.length > 0) {
|
|
16845
|
+
this.chipColorMapEntries = domainColors;
|
|
16846
|
+
this.onChipColorMapChanged();
|
|
16847
|
+
if (!this.chipLabelMapEntries || this.chipLabelMapEntries.length === 0) {
|
|
16848
|
+
const domainLabels = this.resolveDomainLabelMapEntries();
|
|
16849
|
+
if (domainLabels.length > 0) {
|
|
16850
|
+
this.chipLabelMapEntries = domainLabels;
|
|
16851
|
+
this.onChipLabelMapChanged();
|
|
16852
|
+
}
|
|
16853
|
+
}
|
|
16854
|
+
return;
|
|
16855
|
+
}
|
|
16181
16856
|
const locale = this.defaultPresetLocale().toLowerCase();
|
|
16182
16857
|
this.chipColorMapEntries = locale.startsWith('pt')
|
|
16183
16858
|
? [
|
|
@@ -17593,13 +18268,76 @@ class PraxisListConfigEditor {
|
|
|
17593
18268
|
}
|
|
17594
18269
|
// UI editor hydration already called in ctor
|
|
17595
18270
|
// Ensure UI.sortOptions are kept when saving via Settings Panel
|
|
18271
|
+
isGenericInferredChipColorMap(map) {
|
|
18272
|
+
if (!map)
|
|
18273
|
+
return true;
|
|
18274
|
+
const entries = Object.entries(map);
|
|
18275
|
+
if (entries.length === 0)
|
|
18276
|
+
return true;
|
|
18277
|
+
const genericDefaults = {
|
|
18278
|
+
ativo: 'primary',
|
|
18279
|
+
active: 'primary',
|
|
18280
|
+
true: 'primary',
|
|
18281
|
+
inativo: 'warn',
|
|
18282
|
+
inactive: 'warn',
|
|
18283
|
+
false: 'warn',
|
|
18284
|
+
};
|
|
18285
|
+
return (entries.length === Object.keys(genericDefaults).length &&
|
|
18286
|
+
entries.every(([k, v]) => genericDefaults[k] === v));
|
|
18287
|
+
}
|
|
18288
|
+
isGenericInferredChipLabelMap(map) {
|
|
18289
|
+
if (!map)
|
|
18290
|
+
return true;
|
|
18291
|
+
const entries = Object.entries(map);
|
|
18292
|
+
if (entries.length === 0)
|
|
18293
|
+
return true;
|
|
18294
|
+
const genericDefaults = {
|
|
18295
|
+
true: 'Ativo',
|
|
18296
|
+
false: 'Inativo',
|
|
18297
|
+
ativo: 'Ativo',
|
|
18298
|
+
inativo: 'Inativo',
|
|
18299
|
+
active: 'Ativo',
|
|
18300
|
+
inactive: 'Inativo',
|
|
18301
|
+
};
|
|
18302
|
+
return (entries.length === Object.keys(genericDefaults).length &&
|
|
18303
|
+
entries.every(([k, v]) => genericDefaults[k] === v));
|
|
18304
|
+
}
|
|
17596
18305
|
inferFromFields() {
|
|
17597
18306
|
if (!this.fields?.length)
|
|
17598
18307
|
return;
|
|
18308
|
+
const preTemplating = this.working?.templating;
|
|
18309
|
+
const validFields = new Set(this.fields);
|
|
18310
|
+
const prevTrailingField = String(this.mappingTrailing?.field ?? '').trim();
|
|
18311
|
+
const isPrevTrailingGrounded = !prevTrailingField || validFields.has(prevTrailingField);
|
|
18312
|
+
const hadCustomChipColorMap = isPrevTrailingGrounded &&
|
|
18313
|
+
!this.isGenericInferredChipColorMap(preTemplating?.chipColorMap);
|
|
18314
|
+
const hadCustomChipLabelMap = isPrevTrailingGrounded &&
|
|
18315
|
+
!this.isGenericInferredChipLabelMap(preTemplating?.chipLabelMap);
|
|
17599
18316
|
const inferred = inferListAuthoringDocument(this.buildCurrentDocument(), {
|
|
17600
18317
|
schemaFieldNames: this.fields,
|
|
17601
18318
|
});
|
|
17602
18319
|
this.applyIncomingDocument(inferred);
|
|
18320
|
+
const trailingField = this.mappingTrailing?.field;
|
|
18321
|
+
const isTrailingBoolean = !!trailingField &&
|
|
18322
|
+
this.fieldMetaByName[trailingField]?.type?.toLowerCase() === 'boolean';
|
|
18323
|
+
if (this.mappingTrailing?.type === 'chip' &&
|
|
18324
|
+
trailingField &&
|
|
18325
|
+
!isTrailingBoolean &&
|
|
18326
|
+
!hadCustomChipColorMap) {
|
|
18327
|
+
const domainColors = this.resolveDomainColorMapEntries(trailingField);
|
|
18328
|
+
if (domainColors.length > 0) {
|
|
18329
|
+
this.chipColorMapEntries = domainColors;
|
|
18330
|
+
if (!hadCustomChipLabelMap) {
|
|
18331
|
+
const domainLabels = this.resolveDomainLabelMapEntries(trailingField);
|
|
18332
|
+
if (domainLabels.length > 0) {
|
|
18333
|
+
this.chipLabelMapEntries = domainLabels;
|
|
18334
|
+
}
|
|
18335
|
+
}
|
|
18336
|
+
this.working = this.composeWorkingFromVisualState();
|
|
18337
|
+
this.mappingDirty = false;
|
|
18338
|
+
this.appliedMappingSnapshot = this.getMappingSnapshot();
|
|
18339
|
+
}
|
|
18340
|
+
}
|
|
17603
18341
|
this.markDirty();
|
|
17604
18342
|
this.verify();
|
|
17605
18343
|
}
|
|
@@ -18941,13 +19679,44 @@ const EXECUTIVE_EXPANSION_ITEMS = [
|
|
|
18941
19679
|
events: [
|
|
18942
19680
|
{
|
|
18943
19681
|
title: '02/04/2026',
|
|
18944
|
-
meta: '',
|
|
19682
|
+
meta: 'Tesouraria · R$ 5M',
|
|
18945
19683
|
description: 'Vencimento CDB R$ 5M',
|
|
19684
|
+
badge: 'Agendado',
|
|
19685
|
+
badgeTone: 'info',
|
|
19686
|
+
markerColor: 'info',
|
|
19687
|
+
icon: 'event_available',
|
|
19688
|
+
avatarText: 'AC',
|
|
19689
|
+
children: [
|
|
19690
|
+
{
|
|
19691
|
+
label: 'Liquidacao automatica',
|
|
19692
|
+
description: 'Conta Movimento Principal',
|
|
19693
|
+
meta: 'D+0',
|
|
19694
|
+
badge: 'Pronto',
|
|
19695
|
+
badgeTone: 'success',
|
|
19696
|
+
markerColor: 'success',
|
|
19697
|
+
icon: 'verified',
|
|
19698
|
+
},
|
|
19699
|
+
],
|
|
18946
19700
|
},
|
|
18947
19701
|
{
|
|
18948
19702
|
title: '10/04/2026',
|
|
18949
|
-
meta: '',
|
|
19703
|
+
meta: 'Comite Corporate',
|
|
18950
19704
|
description: 'Renovacao de linha de credito',
|
|
19705
|
+
badge: 'Em revisao',
|
|
19706
|
+
badgeTone: 'warning',
|
|
19707
|
+
markerColor: 'warning',
|
|
19708
|
+
icon: 'schedule',
|
|
19709
|
+
avatarText: 'AC',
|
|
19710
|
+
},
|
|
19711
|
+
{
|
|
19712
|
+
title: '18/04/2026',
|
|
19713
|
+
meta: 'Mesa de Cambio',
|
|
19714
|
+
description: 'Rebalanceamento de hedge cambial Q2',
|
|
19715
|
+
badge: 'Planejado',
|
|
19716
|
+
badgeTone: 'neutral',
|
|
19717
|
+
markerColor: 'neutral',
|
|
19718
|
+
icon: 'currency_exchange',
|
|
19719
|
+
avatarText: 'MC',
|
|
18951
19720
|
},
|
|
18952
19721
|
],
|
|
18953
19722
|
},
|
|
@@ -18992,8 +19761,33 @@ const EXECUTIVE_EXPANSION_ITEMS = [
|
|
|
18992
19761
|
events: [
|
|
18993
19762
|
{
|
|
18994
19763
|
title: '05/04/2026',
|
|
18995
|
-
meta: '',
|
|
19764
|
+
meta: 'Comite Middle · R$ 1.5M',
|
|
18996
19765
|
description: 'Revisao de limite com tesouraria',
|
|
19766
|
+
badge: 'Confirmado',
|
|
19767
|
+
badgeTone: 'info',
|
|
19768
|
+
markerColor: 'info',
|
|
19769
|
+
icon: 'event_available',
|
|
19770
|
+
avatarText: 'CE',
|
|
19771
|
+
children: [
|
|
19772
|
+
{
|
|
19773
|
+
label: 'Validacao de recebiveis',
|
|
19774
|
+
description: 'Bordero de duplicatas auditado',
|
|
19775
|
+
meta: 'Concluido',
|
|
19776
|
+
badge: 'OK',
|
|
19777
|
+
badgeTone: 'success',
|
|
19778
|
+
markerColor: 'success',
|
|
19779
|
+
icon: 'verified',
|
|
19780
|
+
},
|
|
19781
|
+
],
|
|
19782
|
+
},
|
|
19783
|
+
{
|
|
19784
|
+
title: '14/04/2026',
|
|
19785
|
+
meta: 'Motor de Liquidacao',
|
|
19786
|
+
description: 'Conciliacao automatica de travas de domicilio',
|
|
19787
|
+
badge: 'Automatico',
|
|
19788
|
+
badgeTone: 'neutral',
|
|
19789
|
+
markerColor: 'neutral',
|
|
19790
|
+
icon: 'autorenew',
|
|
18997
19791
|
},
|
|
18998
19792
|
],
|
|
18999
19793
|
},
|
|
@@ -19041,8 +19835,24 @@ const EXECUTIVE_EXPANSION_ITEMS = [
|
|
|
19041
19835
|
events: [
|
|
19042
19836
|
{
|
|
19043
19837
|
title: '08/04/2026',
|
|
19044
|
-
meta: '',
|
|
19838
|
+
meta: 'Alcada Executiva · R$ 30M',
|
|
19045
19839
|
description: 'Comite extraordinario de limite',
|
|
19840
|
+
badge: 'Prioritario',
|
|
19841
|
+
badgeTone: 'warning',
|
|
19842
|
+
markerColor: 'warning',
|
|
19843
|
+
icon: 'gavel',
|
|
19844
|
+
avatarText: 'AC',
|
|
19845
|
+
children: [
|
|
19846
|
+
{
|
|
19847
|
+
label: 'Parecer de compliance fiscal',
|
|
19848
|
+
description: 'Certidoes federais e estaduais em validacao',
|
|
19849
|
+
meta: 'SLA 24h',
|
|
19850
|
+
badge: 'Pendente',
|
|
19851
|
+
badgeTone: 'warning',
|
|
19852
|
+
markerColor: 'warning',
|
|
19853
|
+
icon: 'policy',
|
|
19854
|
+
},
|
|
19855
|
+
],
|
|
19046
19856
|
},
|
|
19047
19857
|
],
|
|
19048
19858
|
},
|
|
@@ -19123,8 +19933,24 @@ const EXECUTIVE_EXPANSION_ITEMS = [
|
|
|
19123
19933
|
events: [
|
|
19124
19934
|
{
|
|
19125
19935
|
title: '12/04/2026',
|
|
19126
|
-
meta: '',
|
|
19936
|
+
meta: 'Mesa de Risco & Juridico',
|
|
19127
19937
|
description: 'Follow-up com juridico e mesa de risco',
|
|
19938
|
+
badge: 'Critico',
|
|
19939
|
+
badgeTone: 'danger',
|
|
19940
|
+
markerColor: 'danger',
|
|
19941
|
+
icon: 'warning',
|
|
19942
|
+
avatarText: 'RL',
|
|
19943
|
+
children: [
|
|
19944
|
+
{
|
|
19945
|
+
label: 'Reavaliacao de alienacao fiduciaria',
|
|
19946
|
+
description: 'Laudo de safra atualizado',
|
|
19947
|
+
meta: 'Juridico Agro',
|
|
19948
|
+
badge: 'Em analise',
|
|
19949
|
+
badgeTone: 'warning',
|
|
19950
|
+
markerColor: 'warning',
|
|
19951
|
+
icon: 'description',
|
|
19952
|
+
},
|
|
19953
|
+
],
|
|
19128
19954
|
},
|
|
19129
19955
|
],
|
|
19130
19956
|
},
|
|
@@ -19352,39 +20178,39 @@ class PraxisListDocPageComponent {
|
|
|
19352
20178
|
rowLayout: isExecutiveExpansion
|
|
19353
20179
|
? {
|
|
19354
20180
|
type: 'grid',
|
|
19355
|
-
gap: '
|
|
20181
|
+
gap: '8px',
|
|
19356
20182
|
align: 'center',
|
|
19357
20183
|
class: 'exec-row-layout',
|
|
19358
20184
|
columns: [
|
|
19359
|
-
{ slot: 'leading', width: '
|
|
19360
|
-
{ slot: 'identity', minWidth: '
|
|
20185
|
+
{ slot: 'leading', width: '48px', align: 'center' },
|
|
20186
|
+
{ slot: 'identity', minWidth: '304px' },
|
|
19361
20187
|
{
|
|
19362
20188
|
slot: 'balance',
|
|
19363
|
-
width: '
|
|
20189
|
+
width: '96px',
|
|
19364
20190
|
justify: 'center',
|
|
19365
20191
|
align: 'center',
|
|
19366
20192
|
},
|
|
19367
20193
|
{
|
|
19368
20194
|
slot: 'limit',
|
|
19369
|
-
width: '
|
|
20195
|
+
width: '126px',
|
|
19370
20196
|
justify: 'center',
|
|
19371
20197
|
align: 'center',
|
|
19372
20198
|
},
|
|
19373
20199
|
{
|
|
19374
20200
|
slot: 'risk',
|
|
19375
|
-
width: '
|
|
20201
|
+
width: '80px',
|
|
19376
20202
|
justify: 'center',
|
|
19377
20203
|
align: 'center',
|
|
19378
20204
|
},
|
|
19379
20205
|
{
|
|
19380
20206
|
slot: 'alerts',
|
|
19381
|
-
width: '
|
|
20207
|
+
width: '86px',
|
|
19382
20208
|
justify: 'center',
|
|
19383
20209
|
align: 'center',
|
|
19384
20210
|
},
|
|
19385
20211
|
{
|
|
19386
20212
|
slot: 'owner',
|
|
19387
|
-
width: '
|
|
20213
|
+
width: '140px',
|
|
19388
20214
|
justify: 'start',
|
|
19389
20215
|
align: 'center',
|
|
19390
20216
|
},
|
|
@@ -19396,7 +20222,7 @@ class PraxisListDocPageComponent {
|
|
|
19396
20222
|
},
|
|
19397
20223
|
{
|
|
19398
20224
|
slot: 'expand',
|
|
19399
|
-
width: '
|
|
20225
|
+
width: '30px',
|
|
19400
20226
|
justify: 'center',
|
|
19401
20227
|
align: 'center',
|
|
19402
20228
|
},
|
|
@@ -19442,9 +20268,46 @@ class PraxisListDocPageComponent {
|
|
|
19442
20268
|
{
|
|
19443
20269
|
id: 'events',
|
|
19444
20270
|
title: 'Proximos eventos',
|
|
19445
|
-
type: '
|
|
20271
|
+
type: 'rich-content',
|
|
19446
20272
|
itemsExpr: '${item.events}',
|
|
19447
20273
|
emptyLabel: 'Nenhum evento programado',
|
|
20274
|
+
document: {
|
|
20275
|
+
kind: 'praxis.rich-content',
|
|
20276
|
+
version: '1.0.0',
|
|
20277
|
+
nodes: [
|
|
20278
|
+
{
|
|
20279
|
+
type: 'timeline',
|
|
20280
|
+
itemLayout: 'stacked',
|
|
20281
|
+
markerStyle: 'soft',
|
|
20282
|
+
initialLimit: 2,
|
|
20283
|
+
itemsExpr: 'item.events',
|
|
20284
|
+
itemTemplate: {
|
|
20285
|
+
titleExpr: 'item.description',
|
|
20286
|
+
subtitleExpr: 'item.meta',
|
|
20287
|
+
metaExpr: 'item.title',
|
|
20288
|
+
badgeExpr: 'item.badge',
|
|
20289
|
+
badgeTone: '${item.badgeTone}',
|
|
20290
|
+
markerColor: '${item.markerColor}',
|
|
20291
|
+
iconExpr: 'item.icon',
|
|
20292
|
+
avatar: {
|
|
20293
|
+
type: 'avatar',
|
|
20294
|
+
initialsExpr: 'item.avatarText',
|
|
20295
|
+
},
|
|
20296
|
+
children: [
|
|
20297
|
+
{
|
|
20298
|
+
titleExpr: 'item.label',
|
|
20299
|
+
subtitleExpr: 'item.description',
|
|
20300
|
+
metaExpr: 'item.meta',
|
|
20301
|
+
badgeExpr: 'item.badge',
|
|
20302
|
+
badgeTone: '${item.badgeTone}',
|
|
20303
|
+
markerColor: '${item.markerColor}',
|
|
20304
|
+
iconExpr: 'item.icon',
|
|
20305
|
+
},
|
|
20306
|
+
],
|
|
20307
|
+
},
|
|
20308
|
+
},
|
|
20309
|
+
],
|
|
20310
|
+
},
|
|
19448
20311
|
},
|
|
19449
20312
|
],
|
|
19450
20313
|
}
|
|
@@ -19974,7 +20837,7 @@ export class ListDocHostComponent {}`;
|
|
|
19974
20837
|
useFactory: () => new LocalStorageAsyncAdapter(new LocalStorageConfigService()),
|
|
19975
20838
|
},
|
|
19976
20839
|
{ provide: SETTINGS_PANEL_DATA, useValue: {} },
|
|
19977
|
-
], ngImport: i0, template: "<section class=\"list-doc-page\">\n <section class=\"lab\">\n <aside class=\"controls\">\n <article class=\"panel panel--controls\">\n <h2>Playground</h2>\n <p class=\"muted\">\n Ajuste os controles e observe o comportamento da lista em tempo real.\n </p>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Cenario</p>\n <div class=\"chip-row\">\n @for (option of scenarioOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'scenario-' + option.id\"\n [class.is-active]=\"scenario() === option.id\"\n (click)=\"setScenario(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (activeScenarioMeta(); as activeScenario) {\n <p class=\"control-hint\">{{ activeScenario.helper }}</p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Variant</p>\n <div class=\"chip-row\">\n @for (option of variantOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'variant-' + option.id\"\n [class.is-active]=\"variant() === option.id\"\n [disabled]=\"\n isExecutiveExpansionScenario() && option.id !== 'list'\n \"\n (click)=\"setVariant(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Este cenario fixa <code>variant = list</code> para validar a\n detail row inline da V1.\n </p>\n }\n </div>\n\n <div class=\"control-grid\">\n <div class=\"control-block\">\n <p class=\"control-block__title\">Density</p>\n <div class=\"chip-row\">\n @for (option of densityOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'density-' + option.id\"\n [class.is-active]=\"density() === option.id\"\n (click)=\"setDensity(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Lines</p>\n <div class=\"chip-row\">\n @for (count of [1, 2, 3]; track count) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'lines-' + count\"\n [class.is-active]=\"lines() === count\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setLines($any(count))\"\n >\n {{ count }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Linhas travadas em 2 para manter aderencia a referencia\n executiva.\n </p>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Skin</p>\n <div class=\"chip-row\">\n @for (option of skinOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'skin-' + option.id\"\n [class.is-active]=\"skin() === option.id\"\n (click)=\"setSkin(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Features mode</p>\n <div class=\"chip-row\">\n @for (option of featuresModeOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'features-' + option.id\"\n [class.is-active]=\"featuresMode() === option.id\"\n (click)=\"setFeaturesMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Selection</p>\n <div class=\"chip-row\">\n @for (option of selectionOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'selection-' + option.id\"\n [class.is-active]=\"selectionMode() === option.id\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setSelectionMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Selecao desabilitada neste exemplo para evitar conflito com\n expansao por linha.\n </p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Customization mode</p>\n <div class=\"chip-row\">\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-on\"\n [class.is-active]=\"customizationEnabled()\"\n (click)=\"setCustomizationMode(true)\"\n >\n On\n </button>\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-off\"\n [class.is-active]=\"!customizationEnabled()\"\n (click)=\"setCustomizationMode(false)\"\n >\n Off\n </button>\n </div>\n <p class=\"control-hint\">\n Ative para exibir editor interno + AI assistant do componente.\n </p>\n </div>\n </article>\n\n <article class=\"panel panel--events\">\n <div class=\"panel__head\">\n <h2>Eventos</h2>\n <button\n type=\"button\"\n class=\"ghost-btn\"\n data-testid=\"clear-log\"\n (click)=\"clearLog()\"\n >\n Limpar log\n </button>\n </div>\n @if (eventLog().length === 0) {\n <p class=\"muted\">\n Sem eventos ainda. Clique em itens, acoes ou selecao.\n </p>\n } @else {\n <ul class=\"event-log\">\n @for (entry of eventLog(); track entry.id) {\n <li>{{ entry.message }}</li>\n }\n </ul>\n }\n </article>\n </aside>\n\n <article class=\"panel panel--live\">\n <h2>Exemplo live</h2>\n <p class=\"muted\">\n Mostra list/cards/tiles com os mesmos dados e configura em tempo real.\n </p>\n @if (scenario() === \"executive-expansion\") {\n <p class=\"muted\">\n Cenario canonico da V1 para validar linha executiva com detail row\n inline e owner de expansao dedicado.\n </p>\n }\n <praxis-list\n listId=\"praxis-list-doc-live\"\n componentInstanceId=\"main-showcase\"\n [config]=\"liveConfig()\"\n [form]=\"form\"\n [enableCustomization]=\"customizationEnabled()\"\n (itemClick)=\"handleItemClick($event)\"\n (actionClick)=\"handleActionClick($event)\"\n (selectionChange)=\"handleSelectionChange($event)\"\n />\n </article>\n </section>\n\n <section class=\"skin-matrix\">\n <div class=\"section-head\">\n <h2>Matriz de skins</h2>\n <p>\n Preview rapido de todos os estilos visuais disponiveis no componente.\n </p>\n </div>\n <div class=\"skin-matrix__grid\">\n @for (preview of skinPreviewConfigs(); track preview.type) {\n <article class=\"panel skin-preview\">\n <h3>{{ preview.type }}</h3>\n <praxis-list-skin-preview\n [config]=\"preview.config\"\n [items]=\"skinPreviewItems\"\n />\n </article>\n }\n </div>\n </section>\n\n <section class=\"code-lab panel\">\n <div class=\"section-head\">\n <h2>Snippets de referencia</h2>\n <p>\n Use os blocos abaixo para replicar os exemplos no host ou no site de\n documentacao.\n </p>\n </div>\n\n <div class=\"code-tabs\">\n @for (tab of codeTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.is-active]=\"activeTab() === tab.id\"\n (click)=\"setCodeTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <pre class=\"code-box\"><code>{{ selectedSnippet() }}</code></pre>\n </section>\n\n <section class=\"notes panel\">\n <h2>Notas de arquitetura</h2>\n <ul>\n <li>\n <strong>Persistencia:</strong> sempre definir <code>listId</code>; para\n multiplas instancias, use <code>componentInstanceId</code>.\n </li>\n <li>\n <strong>Local vs remoto:</strong> <code>dataSource.data</code> tem\n precedencia para preview local; <code>resourcePath</code> define o\n contrato remoto.\n </li>\n <li>\n <strong>Toolbar remota:</strong> controles de paginacao/sort/busca\n refletem o contrato; a semantica completa de filtro/paginacao depende do\n backend em <code>/filter</code>.\n </li>\n <li>\n <strong>Editor interno:</strong> habilite\n <code>enableCustomization</code> quando o host tiver os providers de\n Settings Panel e AI.\n </li>\n <li>\n <strong>A11y:</strong> configure <code>a11y.ariaLabel</code>/<code\n >ariaLabelledBy</code\n >\n e mantenha labels de acoes explicitas.\n </li>\n <li>\n <strong>Expansao inline V1:</strong> suportada apenas em\n <code>layout.variant = list</code>.\n </li>\n <li>\n <strong>Selecao + expansao:</strong> quando houver selecao, o trigger\n canonico e por icone para evitar ambiguidade operacional.\n </li>\n </ul>\n </section>\n</section>\n", styles: [":host{display:block}.list-doc-page{--doc-bg: linear-gradient(160deg, #eef5ff 0%, #f9fbff 48%, #e8f7ef 100%);--doc-surface: rgba(255, 255, 255, .86);--doc-surface-strong: #ffffff;--doc-border: #cfdae8;--doc-text: #10243a;--doc-muted: #4d6075;--doc-accent: #0b6dff;--doc-accent-2: #0f9d58;--doc-accent-soft: color-mix(in srgb, var(--doc-accent) 15%, #ffffff);display:grid;gap:20px;padding:18px;border-radius:22px;border:1px solid var(--doc-border);color:var(--doc-text);background:var(--doc-bg);font-family:Manrope,Segoe UI,sans-serif}.hero{display:grid;gap:16px;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}.hero__copy{border-radius:18px;border:1px solid var(--doc-border);padding:18px;background:radial-gradient(120% 130% at 0% 0%,rgba(11,109,255,.2),transparent 56%),var(--doc-surface-strong);box-shadow:0 14px 24px #0a254c14}.hero__eyebrow{margin:0 0 8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#385f9c;font-weight:700}.hero h1{margin:0;font-size:clamp(1.24rem,2.8vw,1.86rem);line-height:1.25}.hero h1 code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 28%,#cad6ec);border-radius:8px;padding:2px 6px;font-size:.9em}.hero p{margin:10px 0 0;color:var(--doc-muted)}.hero__badges{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px}.hero__badges span{border-radius:999px;border:1px solid color-mix(in srgb,#0f9d58 26%,#cad9d2);background:color-mix(in srgb,#0f9d58 12%,#ffffff);color:#0f5d39;padding:5px 10px;font-size:12px;font-weight:700}.hero__panel{border-radius:18px;border:1px solid var(--doc-border);padding:16px;background:var(--doc-surface);box-shadow:0 10px 20px #182e5414}.hero__panel-title{margin:0 0 10px;font-size:13px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#345684}.hero__panel ul{margin:0;padding:0;list-style:none;display:grid;gap:8px}.hero__panel li{display:grid;gap:2px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,#274f82 14%,#d1d8e6);background:#fff}.hero__panel strong{font-size:12px}.hero__panel span{color:var(--doc-muted);font-size:12px}.lab{display:grid;gap:14px;grid-template-columns:minmax(260px,340px) minmax(0,1fr);align-items:start}.controls{display:grid;gap:12px}.panel{border-radius:16px;border:1px solid var(--doc-border);background:var(--doc-surface);box-shadow:0 8px 18px #1b2d4f12}.panel--controls,.panel--events{padding:14px}.panel--controls h2,.panel--live h2,.panel--events h2,.skin-preview h3,.code-lab h2,.notes h2{margin:0}.panel--live{padding:14px;min-width:0}.muted{margin:6px 0 0;color:var(--doc-muted);font-size:13px}.control-block{margin-top:12px}.control-grid{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr))}.control-block__title{margin:0 0 6px;font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#325d96}.control-hint{margin:8px 0 0;color:var(--doc-muted);font-size:12px}.chip-row{display:flex;gap:7px;flex-wrap:wrap}.chip-button{min-height:30px;border-radius:999px;border:1px solid color-mix(in srgb,#225ea9 30%,#c8d3e3);background:#f4f8ff;color:#1f3f69;padding:0 12px;font-size:12px;font-weight:700;cursor:pointer;transition:.14s ease;transition-property:border-color,background,color,transform}.chip-button--small{min-height:28px;padding-inline:10px;font-size:11px}.chip-button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--doc-accent) 44%,#a6bad7)}.chip-button.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#6f8aa9);background:linear-gradient(140deg,#1565d8,#0f9360);color:#fff}.chip-button:focus-visible,.ghost-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 65%,#416688);outline-offset:1px}.panel__head{display:flex;gap:10px;justify-content:space-between;align-items:center}.ghost-btn{min-height:30px;border-radius:8px;border:1px solid color-mix(in srgb,#173d6e 32%,#cdd7e4);background:#fff;color:#1f3d66;font-size:12px;font-weight:700;padding:0 10px;cursor:pointer}.event-log{margin:10px 0 0;padding:0;list-style:none;display:grid;gap:6px}.event-log li{border-radius:9px;border:1px solid color-mix(in srgb,#34598a 16%,#ccd7e6);background:#fff;padding:7px 9px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;color:#273e5f}.skin-matrix{display:grid;gap:10px}.section-head h2{margin:0}.section-head p{margin:4px 0 0;color:var(--doc-muted)}.skin-matrix__grid{display:grid;gap:12px;width:100%;max-width:1840px;margin-inline:auto;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}.skin-preview{padding:12px;min-width:0}.skin-preview h3{margin-bottom:8px;text-transform:capitalize}.code-lab{padding:14px}.code-tabs{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap}.code-box{margin:12px 0 0;border-radius:12px;border:1px solid color-mix(in srgb,#2d3f58 36%,#8194aa);background:#0d1420;color:#d9ecff;padding:12px;max-height:360px;overflow:auto;font-size:12px;line-height:1.55}.notes{padding:14px}.notes ul{margin:10px 0 0;padding-left:18px;display:grid;gap:8px}.notes li{color:#21354f}.notes code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 30%,#c8d5e7);border-radius:6px;padding:1px 5px}@media(max-width:1060px){.hero,.lab{grid-template-columns:1fr}}@media(max-width:700px){.list-doc-page{padding:12px}.control-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PraxisList, selector: "praxis-list", inputs: ["config", "listId", "componentInstanceId", "configPersistenceStrategy", "queryContext", "form", "enableCustomization", "itemActions", "virtualScroll"], outputs: ["itemClick", "actionClick", "selectionChange", "exportAction", "configPatchChange"] }, { kind: "component", type: PraxisListSkinPreviewComponent, selector: "praxis-list-skin-preview", inputs: ["config", "items", "theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20840
|
+
], ngImport: i0, template: "<section class=\"list-doc-page\">\n <section class=\"lab\">\n <aside class=\"controls\">\n <article class=\"panel panel--controls\">\n <h2>Playground</h2>\n <p class=\"muted\">\n Ajuste os controles e observe o comportamento da lista em tempo real.\n </p>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Cenario</p>\n <div class=\"chip-row\">\n @for (option of scenarioOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'scenario-' + option.id\"\n [class.is-active]=\"scenario() === option.id\"\n (click)=\"setScenario(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (activeScenarioMeta(); as activeScenario) {\n <p class=\"control-hint\">{{ activeScenario.helper }}</p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Variant</p>\n <div class=\"chip-row\">\n @for (option of variantOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'variant-' + option.id\"\n [class.is-active]=\"variant() === option.id\"\n [disabled]=\"\n isExecutiveExpansionScenario() && option.id !== 'list'\n \"\n (click)=\"setVariant(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Este cenario fixa <code>variant = list</code> para validar a\n detail row inline da V1.\n </p>\n }\n </div>\n\n <div class=\"control-grid\">\n <div class=\"control-block\">\n <p class=\"control-block__title\">Density</p>\n <div class=\"chip-row\">\n @for (option of densityOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'density-' + option.id\"\n [class.is-active]=\"density() === option.id\"\n (click)=\"setDensity(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Lines</p>\n <div class=\"chip-row\">\n @for (count of [1, 2, 3]; track count) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'lines-' + count\"\n [class.is-active]=\"lines() === count\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setLines($any(count))\"\n >\n {{ count }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Linhas travadas em 2 para manter aderencia a referencia\n executiva.\n </p>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Skin</p>\n <div class=\"chip-row\">\n @for (option of skinOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'skin-' + option.id\"\n [class.is-active]=\"skin() === option.id\"\n (click)=\"setSkin(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Features mode</p>\n <div class=\"chip-row\">\n @for (option of featuresModeOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'features-' + option.id\"\n [class.is-active]=\"featuresMode() === option.id\"\n (click)=\"setFeaturesMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Selection</p>\n <div class=\"chip-row\">\n @for (option of selectionOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'selection-' + option.id\"\n [class.is-active]=\"selectionMode() === option.id\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setSelectionMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Selecao desabilitada neste exemplo para evitar conflito com\n expansao por linha.\n </p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Customization mode</p>\n <div class=\"chip-row\">\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-on\"\n [class.is-active]=\"customizationEnabled()\"\n (click)=\"setCustomizationMode(true)\"\n >\n On\n </button>\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-off\"\n [class.is-active]=\"!customizationEnabled()\"\n (click)=\"setCustomizationMode(false)\"\n >\n Off\n </button>\n </div>\n <p class=\"control-hint\">\n Ative para exibir editor interno + AI assistant do componente.\n </p>\n </div>\n </article>\n\n <article class=\"panel panel--events\">\n <div class=\"panel__head\">\n <h2>Eventos</h2>\n <button\n type=\"button\"\n class=\"ghost-btn\"\n data-testid=\"clear-log\"\n (click)=\"clearLog()\"\n >\n Limpar log\n </button>\n </div>\n @if (eventLog().length === 0) {\n <p class=\"muted\">\n Sem eventos ainda. Clique em itens, acoes ou selecao.\n </p>\n } @else {\n <ul class=\"event-log\">\n @for (entry of eventLog(); track entry.id) {\n <li>{{ entry.message }}</li>\n }\n </ul>\n }\n </article>\n </aside>\n\n <article class=\"panel panel--live\">\n <h2>Exemplo live</h2>\n <p class=\"muted\">\n Mostra list/cards/tiles com os mesmos dados e configura em tempo real.\n </p>\n @if (scenario() === \"executive-expansion\") {\n <p class=\"muted\">\n Cenario canonico da V1 para validar linha executiva com detail row\n inline e owner de expansao dedicado.\n </p>\n }\n <praxis-list\n listId=\"praxis-list-doc-live\"\n componentInstanceId=\"main-showcase\"\n [config]=\"liveConfig()\"\n [form]=\"form\"\n [enableCustomization]=\"customizationEnabled()\"\n (itemClick)=\"handleItemClick($event)\"\n (actionClick)=\"handleActionClick($event)\"\n (selectionChange)=\"handleSelectionChange($event)\"\n />\n </article>\n </section>\n\n <section class=\"skin-matrix\">\n <div class=\"section-head\">\n <h2>Matriz de skins</h2>\n <p>\n Preview rapido de todos os estilos visuais disponiveis no componente.\n </p>\n </div>\n <div class=\"skin-matrix__grid\">\n @for (preview of skinPreviewConfigs(); track preview.type) {\n <article class=\"panel skin-preview\">\n <h3>{{ preview.type }}</h3>\n <praxis-list-skin-preview\n [config]=\"preview.config\"\n [items]=\"skinPreviewItems\"\n />\n </article>\n }\n </div>\n </section>\n\n <section class=\"code-lab panel\">\n <div class=\"section-head\">\n <h2>Snippets de referencia</h2>\n <p>\n Use os blocos abaixo para replicar os exemplos no host ou no site de\n documentacao.\n </p>\n </div>\n\n <div class=\"code-tabs\">\n @for (tab of codeTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.is-active]=\"activeTab() === tab.id\"\n (click)=\"setCodeTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <pre class=\"code-box\"><code>{{ selectedSnippet() }}</code></pre>\n </section>\n\n <section class=\"notes panel\">\n <h2>Notas de arquitetura</h2>\n <ul>\n <li>\n <strong>Persistencia:</strong> sempre definir <code>listId</code>; para\n multiplas instancias, use <code>componentInstanceId</code>.\n </li>\n <li>\n <strong>Local vs remoto:</strong> <code>dataSource.data</code> tem\n precedencia para preview local; <code>resourcePath</code> define o\n contrato remoto.\n </li>\n <li>\n <strong>Toolbar remota:</strong> controles de paginacao/sort/busca\n refletem o contrato; a semantica completa de filtro/paginacao depende do\n backend em <code>/filter</code>.\n </li>\n <li>\n <strong>Editor interno:</strong> habilite\n <code>enableCustomization</code> quando o host tiver os providers de\n Settings Panel e AI.\n </li>\n <li>\n <strong>A11y:</strong> configure <code>a11y.ariaLabel</code>/<code\n >ariaLabelledBy</code\n >\n e mantenha labels de acoes explicitas.\n </li>\n <li>\n <strong>Expansao inline V1:</strong> suportada apenas em\n <code>layout.variant = list</code>.\n </li>\n <li>\n <strong>Selecao + expansao:</strong> quando houver selecao, o trigger\n canonico e por icone para evitar ambiguidade operacional.\n </li>\n </ul>\n </section>\n</section>\n", styles: [":host{display:block}.list-doc-page{--doc-bg: linear-gradient(160deg, #eef5ff 0%, #f9fbff 48%, #e8f7ef 100%);--doc-surface: rgba(255, 255, 255, .86);--doc-surface-strong: #ffffff;--doc-border: #cfdae8;--doc-text: #10243a;--doc-muted: #4d6075;--doc-accent: #0b6dff;--doc-accent-2: #0f9d58;--doc-accent-soft: color-mix(in srgb, var(--doc-accent) 15%, #ffffff);display:grid;gap:20px;padding:18px;border-radius:22px;border:1px solid var(--doc-border);color:var(--doc-text);background:var(--doc-bg);font-family:Manrope,Segoe UI,sans-serif}.hero{display:grid;gap:16px;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}.hero__copy{border-radius:18px;border:1px solid var(--doc-border);padding:18px;background:radial-gradient(120% 130% at 0% 0%,rgba(11,109,255,.2),transparent 56%),var(--doc-surface-strong);box-shadow:0 14px 24px #0a254c14}.hero__eyebrow{margin:0 0 8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#385f9c;font-weight:700}.hero h1{margin:0;font-size:clamp(1.24rem,2.8vw,1.86rem);line-height:1.25}.hero h1 code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 28%,#cad6ec);border-radius:8px;padding:2px 6px;font-size:.9em}.hero p{margin:10px 0 0;color:var(--doc-muted)}.hero__badges{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px}.hero__badges span{border-radius:999px;border:1px solid color-mix(in srgb,#0f9d58 26%,#cad9d2);background:color-mix(in srgb,#0f9d58 12%,#ffffff);color:#0f5d39;padding:5px 10px;font-size:12px;font-weight:700}.hero__panel{border-radius:18px;border:1px solid var(--doc-border);padding:16px;background:var(--doc-surface);box-shadow:0 10px 20px #182e5414}.hero__panel-title{margin:0 0 10px;font-size:13px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#345684}.hero__panel ul{margin:0;padding:0;list-style:none;display:grid;gap:8px}.hero__panel li{display:grid;gap:2px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,#274f82 14%,#d1d8e6);background:#fff}.hero__panel strong{font-size:12px}.hero__panel span{color:var(--doc-muted);font-size:12px}.lab{display:grid;gap:14px;grid-template-columns:minmax(200px,240px) minmax(0,1fr);align-items:start}.controls{display:grid;gap:12px}.panel{border-radius:16px;border:1px solid var(--doc-border);background:var(--doc-surface);box-shadow:0 8px 18px #1b2d4f12}.panel--controls,.panel--events{padding:14px}.panel--controls h2,.panel--live h2,.panel--events h2,.skin-preview h3,.code-lab h2,.notes h2{margin:0}.panel--live{padding:14px;min-width:0}.muted{margin:6px 0 0;color:var(--doc-muted);font-size:13px}.control-block{margin-top:12px}.control-grid{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr))}.control-block__title{margin:0 0 6px;font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#325d96}.control-hint{margin:8px 0 0;color:var(--doc-muted);font-size:12px}.chip-row{display:flex;gap:7px;flex-wrap:wrap}.chip-button{min-height:30px;border-radius:999px;border:1px solid color-mix(in srgb,#225ea9 30%,#c8d3e3);background:#f4f8ff;color:#1f3f69;padding:0 12px;font-size:12px;font-weight:700;cursor:pointer;transition:.14s ease;transition-property:border-color,background,color,transform}.chip-button--small{min-height:28px;padding-inline:10px;font-size:11px}.chip-button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--doc-accent) 44%,#a6bad7)}.chip-button.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#6f8aa9);background:linear-gradient(140deg,#1565d8,#0f9360);color:#fff}.chip-button:focus-visible,.ghost-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 65%,#416688);outline-offset:1px}.panel__head{display:flex;gap:10px;justify-content:space-between;align-items:center}.ghost-btn{min-height:30px;border-radius:8px;border:1px solid color-mix(in srgb,#173d6e 32%,#cdd7e4);background:#fff;color:#1f3d66;font-size:12px;font-weight:700;padding:0 10px;cursor:pointer}.event-log{margin:10px 0 0;padding:0;list-style:none;display:grid;gap:6px}.event-log li{border-radius:9px;border:1px solid color-mix(in srgb,#34598a 16%,#ccd7e6);background:#fff;padding:7px 9px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;color:#273e5f}.skin-matrix{display:grid;gap:10px}.section-head h2{margin:0}.section-head p{margin:4px 0 0;color:var(--doc-muted)}.skin-matrix__grid{display:grid;gap:12px;width:100%;max-width:1840px;margin-inline:auto;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}.skin-preview{padding:12px;min-width:0}.skin-preview h3{margin-bottom:8px;text-transform:capitalize}.code-lab{padding:14px}.code-tabs{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap}.code-box{margin:12px 0 0;border-radius:12px;border:1px solid color-mix(in srgb,#2d3f58 36%,#8194aa);background:#0d1420;color:#d9ecff;padding:12px;max-height:360px;overflow:auto;font-size:12px;line-height:1.55}.notes{padding:14px}.notes ul{margin:10px 0 0;padding-left:18px;display:grid;gap:8px}.notes li{color:#21354f}.notes code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 30%,#c8d5e7);border-radius:6px;padding:1px 5px}@media(max-width:1060px){.hero,.lab{grid-template-columns:1fr}}@media(max-width:700px){.list-doc-page{padding:12px}.control-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PraxisList, selector: "praxis-list", inputs: ["config", "listId", "componentInstanceId", "configPersistenceStrategy", "queryContext", "form", "enableCustomization", "itemActions", "virtualScroll"], outputs: ["itemClick", "actionClick", "selectionChange", "exportAction", "configPatchChange"] }, { kind: "component", type: PraxisListSkinPreviewComponent, selector: "praxis-list-skin-preview", inputs: ["config", "items", "theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
19978
20841
|
}
|
|
19979
20842
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisListDocPageComponent, decorators: [{
|
|
19980
20843
|
type: Component,
|
|
@@ -19989,7 +20852,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
19989
20852
|
useFactory: () => new LocalStorageAsyncAdapter(new LocalStorageConfigService()),
|
|
19990
20853
|
},
|
|
19991
20854
|
{ provide: SETTINGS_PANEL_DATA, useValue: {} },
|
|
19992
|
-
], template: "<section class=\"list-doc-page\">\n <section class=\"lab\">\n <aside class=\"controls\">\n <article class=\"panel panel--controls\">\n <h2>Playground</h2>\n <p class=\"muted\">\n Ajuste os controles e observe o comportamento da lista em tempo real.\n </p>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Cenario</p>\n <div class=\"chip-row\">\n @for (option of scenarioOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'scenario-' + option.id\"\n [class.is-active]=\"scenario() === option.id\"\n (click)=\"setScenario(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (activeScenarioMeta(); as activeScenario) {\n <p class=\"control-hint\">{{ activeScenario.helper }}</p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Variant</p>\n <div class=\"chip-row\">\n @for (option of variantOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'variant-' + option.id\"\n [class.is-active]=\"variant() === option.id\"\n [disabled]=\"\n isExecutiveExpansionScenario() && option.id !== 'list'\n \"\n (click)=\"setVariant(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Este cenario fixa <code>variant = list</code> para validar a\n detail row inline da V1.\n </p>\n }\n </div>\n\n <div class=\"control-grid\">\n <div class=\"control-block\">\n <p class=\"control-block__title\">Density</p>\n <div class=\"chip-row\">\n @for (option of densityOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'density-' + option.id\"\n [class.is-active]=\"density() === option.id\"\n (click)=\"setDensity(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Lines</p>\n <div class=\"chip-row\">\n @for (count of [1, 2, 3]; track count) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'lines-' + count\"\n [class.is-active]=\"lines() === count\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setLines($any(count))\"\n >\n {{ count }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Linhas travadas em 2 para manter aderencia a referencia\n executiva.\n </p>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Skin</p>\n <div class=\"chip-row\">\n @for (option of skinOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'skin-' + option.id\"\n [class.is-active]=\"skin() === option.id\"\n (click)=\"setSkin(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Features mode</p>\n <div class=\"chip-row\">\n @for (option of featuresModeOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'features-' + option.id\"\n [class.is-active]=\"featuresMode() === option.id\"\n (click)=\"setFeaturesMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Selection</p>\n <div class=\"chip-row\">\n @for (option of selectionOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'selection-' + option.id\"\n [class.is-active]=\"selectionMode() === option.id\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setSelectionMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Selecao desabilitada neste exemplo para evitar conflito com\n expansao por linha.\n </p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Customization mode</p>\n <div class=\"chip-row\">\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-on\"\n [class.is-active]=\"customizationEnabled()\"\n (click)=\"setCustomizationMode(true)\"\n >\n On\n </button>\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-off\"\n [class.is-active]=\"!customizationEnabled()\"\n (click)=\"setCustomizationMode(false)\"\n >\n Off\n </button>\n </div>\n <p class=\"control-hint\">\n Ative para exibir editor interno + AI assistant do componente.\n </p>\n </div>\n </article>\n\n <article class=\"panel panel--events\">\n <div class=\"panel__head\">\n <h2>Eventos</h2>\n <button\n type=\"button\"\n class=\"ghost-btn\"\n data-testid=\"clear-log\"\n (click)=\"clearLog()\"\n >\n Limpar log\n </button>\n </div>\n @if (eventLog().length === 0) {\n <p class=\"muted\">\n Sem eventos ainda. Clique em itens, acoes ou selecao.\n </p>\n } @else {\n <ul class=\"event-log\">\n @for (entry of eventLog(); track entry.id) {\n <li>{{ entry.message }}</li>\n }\n </ul>\n }\n </article>\n </aside>\n\n <article class=\"panel panel--live\">\n <h2>Exemplo live</h2>\n <p class=\"muted\">\n Mostra list/cards/tiles com os mesmos dados e configura em tempo real.\n </p>\n @if (scenario() === \"executive-expansion\") {\n <p class=\"muted\">\n Cenario canonico da V1 para validar linha executiva com detail row\n inline e owner de expansao dedicado.\n </p>\n }\n <praxis-list\n listId=\"praxis-list-doc-live\"\n componentInstanceId=\"main-showcase\"\n [config]=\"liveConfig()\"\n [form]=\"form\"\n [enableCustomization]=\"customizationEnabled()\"\n (itemClick)=\"handleItemClick($event)\"\n (actionClick)=\"handleActionClick($event)\"\n (selectionChange)=\"handleSelectionChange($event)\"\n />\n </article>\n </section>\n\n <section class=\"skin-matrix\">\n <div class=\"section-head\">\n <h2>Matriz de skins</h2>\n <p>\n Preview rapido de todos os estilos visuais disponiveis no componente.\n </p>\n </div>\n <div class=\"skin-matrix__grid\">\n @for (preview of skinPreviewConfigs(); track preview.type) {\n <article class=\"panel skin-preview\">\n <h3>{{ preview.type }}</h3>\n <praxis-list-skin-preview\n [config]=\"preview.config\"\n [items]=\"skinPreviewItems\"\n />\n </article>\n }\n </div>\n </section>\n\n <section class=\"code-lab panel\">\n <div class=\"section-head\">\n <h2>Snippets de referencia</h2>\n <p>\n Use os blocos abaixo para replicar os exemplos no host ou no site de\n documentacao.\n </p>\n </div>\n\n <div class=\"code-tabs\">\n @for (tab of codeTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.is-active]=\"activeTab() === tab.id\"\n (click)=\"setCodeTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <pre class=\"code-box\"><code>{{ selectedSnippet() }}</code></pre>\n </section>\n\n <section class=\"notes panel\">\n <h2>Notas de arquitetura</h2>\n <ul>\n <li>\n <strong>Persistencia:</strong> sempre definir <code>listId</code>; para\n multiplas instancias, use <code>componentInstanceId</code>.\n </li>\n <li>\n <strong>Local vs remoto:</strong> <code>dataSource.data</code> tem\n precedencia para preview local; <code>resourcePath</code> define o\n contrato remoto.\n </li>\n <li>\n <strong>Toolbar remota:</strong> controles de paginacao/sort/busca\n refletem o contrato; a semantica completa de filtro/paginacao depende do\n backend em <code>/filter</code>.\n </li>\n <li>\n <strong>Editor interno:</strong> habilite\n <code>enableCustomization</code> quando o host tiver os providers de\n Settings Panel e AI.\n </li>\n <li>\n <strong>A11y:</strong> configure <code>a11y.ariaLabel</code>/<code\n >ariaLabelledBy</code\n >\n e mantenha labels de acoes explicitas.\n </li>\n <li>\n <strong>Expansao inline V1:</strong> suportada apenas em\n <code>layout.variant = list</code>.\n </li>\n <li>\n <strong>Selecao + expansao:</strong> quando houver selecao, o trigger\n canonico e por icone para evitar ambiguidade operacional.\n </li>\n </ul>\n </section>\n</section>\n", styles: [":host{display:block}.list-doc-page{--doc-bg: linear-gradient(160deg, #eef5ff 0%, #f9fbff 48%, #e8f7ef 100%);--doc-surface: rgba(255, 255, 255, .86);--doc-surface-strong: #ffffff;--doc-border: #cfdae8;--doc-text: #10243a;--doc-muted: #4d6075;--doc-accent: #0b6dff;--doc-accent-2: #0f9d58;--doc-accent-soft: color-mix(in srgb, var(--doc-accent) 15%, #ffffff);display:grid;gap:20px;padding:18px;border-radius:22px;border:1px solid var(--doc-border);color:var(--doc-text);background:var(--doc-bg);font-family:Manrope,Segoe UI,sans-serif}.hero{display:grid;gap:16px;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}.hero__copy{border-radius:18px;border:1px solid var(--doc-border);padding:18px;background:radial-gradient(120% 130% at 0% 0%,rgba(11,109,255,.2),transparent 56%),var(--doc-surface-strong);box-shadow:0 14px 24px #0a254c14}.hero__eyebrow{margin:0 0 8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#385f9c;font-weight:700}.hero h1{margin:0;font-size:clamp(1.24rem,2.8vw,1.86rem);line-height:1.25}.hero h1 code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 28%,#cad6ec);border-radius:8px;padding:2px 6px;font-size:.9em}.hero p{margin:10px 0 0;color:var(--doc-muted)}.hero__badges{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px}.hero__badges span{border-radius:999px;border:1px solid color-mix(in srgb,#0f9d58 26%,#cad9d2);background:color-mix(in srgb,#0f9d58 12%,#ffffff);color:#0f5d39;padding:5px 10px;font-size:12px;font-weight:700}.hero__panel{border-radius:18px;border:1px solid var(--doc-border);padding:16px;background:var(--doc-surface);box-shadow:0 10px 20px #182e5414}.hero__panel-title{margin:0 0 10px;font-size:13px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#345684}.hero__panel ul{margin:0;padding:0;list-style:none;display:grid;gap:8px}.hero__panel li{display:grid;gap:2px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,#274f82 14%,#d1d8e6);background:#fff}.hero__panel strong{font-size:12px}.hero__panel span{color:var(--doc-muted);font-size:12px}.lab{display:grid;gap:14px;grid-template-columns:minmax(260px,340px) minmax(0,1fr);align-items:start}.controls{display:grid;gap:12px}.panel{border-radius:16px;border:1px solid var(--doc-border);background:var(--doc-surface);box-shadow:0 8px 18px #1b2d4f12}.panel--controls,.panel--events{padding:14px}.panel--controls h2,.panel--live h2,.panel--events h2,.skin-preview h3,.code-lab h2,.notes h2{margin:0}.panel--live{padding:14px;min-width:0}.muted{margin:6px 0 0;color:var(--doc-muted);font-size:13px}.control-block{margin-top:12px}.control-grid{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr))}.control-block__title{margin:0 0 6px;font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#325d96}.control-hint{margin:8px 0 0;color:var(--doc-muted);font-size:12px}.chip-row{display:flex;gap:7px;flex-wrap:wrap}.chip-button{min-height:30px;border-radius:999px;border:1px solid color-mix(in srgb,#225ea9 30%,#c8d3e3);background:#f4f8ff;color:#1f3f69;padding:0 12px;font-size:12px;font-weight:700;cursor:pointer;transition:.14s ease;transition-property:border-color,background,color,transform}.chip-button--small{min-height:28px;padding-inline:10px;font-size:11px}.chip-button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--doc-accent) 44%,#a6bad7)}.chip-button.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#6f8aa9);background:linear-gradient(140deg,#1565d8,#0f9360);color:#fff}.chip-button:focus-visible,.ghost-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 65%,#416688);outline-offset:1px}.panel__head{display:flex;gap:10px;justify-content:space-between;align-items:center}.ghost-btn{min-height:30px;border-radius:8px;border:1px solid color-mix(in srgb,#173d6e 32%,#cdd7e4);background:#fff;color:#1f3d66;font-size:12px;font-weight:700;padding:0 10px;cursor:pointer}.event-log{margin:10px 0 0;padding:0;list-style:none;display:grid;gap:6px}.event-log li{border-radius:9px;border:1px solid color-mix(in srgb,#34598a 16%,#ccd7e6);background:#fff;padding:7px 9px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;color:#273e5f}.skin-matrix{display:grid;gap:10px}.section-head h2{margin:0}.section-head p{margin:4px 0 0;color:var(--doc-muted)}.skin-matrix__grid{display:grid;gap:12px;width:100%;max-width:1840px;margin-inline:auto;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}.skin-preview{padding:12px;min-width:0}.skin-preview h3{margin-bottom:8px;text-transform:capitalize}.code-lab{padding:14px}.code-tabs{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap}.code-box{margin:12px 0 0;border-radius:12px;border:1px solid color-mix(in srgb,#2d3f58 36%,#8194aa);background:#0d1420;color:#d9ecff;padding:12px;max-height:360px;overflow:auto;font-size:12px;line-height:1.55}.notes{padding:14px}.notes ul{margin:10px 0 0;padding-left:18px;display:grid;gap:8px}.notes li{color:#21354f}.notes code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 30%,#c8d5e7);border-radius:6px;padding:1px 5px}@media(max-width:1060px){.hero,.lab{grid-template-columns:1fr}}@media(max-width:700px){.list-doc-page{padding:12px}.control-grid{grid-template-columns:1fr}}\n"] }]
|
|
20855
|
+
], template: "<section class=\"list-doc-page\">\n <section class=\"lab\">\n <aside class=\"controls\">\n <article class=\"panel panel--controls\">\n <h2>Playground</h2>\n <p class=\"muted\">\n Ajuste os controles e observe o comportamento da lista em tempo real.\n </p>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Cenario</p>\n <div class=\"chip-row\">\n @for (option of scenarioOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'scenario-' + option.id\"\n [class.is-active]=\"scenario() === option.id\"\n (click)=\"setScenario(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (activeScenarioMeta(); as activeScenario) {\n <p class=\"control-hint\">{{ activeScenario.helper }}</p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Variant</p>\n <div class=\"chip-row\">\n @for (option of variantOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'variant-' + option.id\"\n [class.is-active]=\"variant() === option.id\"\n [disabled]=\"\n isExecutiveExpansionScenario() && option.id !== 'list'\n \"\n (click)=\"setVariant(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Este cenario fixa <code>variant = list</code> para validar a\n detail row inline da V1.\n </p>\n }\n </div>\n\n <div class=\"control-grid\">\n <div class=\"control-block\">\n <p class=\"control-block__title\">Density</p>\n <div class=\"chip-row\">\n @for (option of densityOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'density-' + option.id\"\n [class.is-active]=\"density() === option.id\"\n (click)=\"setDensity(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Lines</p>\n <div class=\"chip-row\">\n @for (count of [1, 2, 3]; track count) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'lines-' + count\"\n [class.is-active]=\"lines() === count\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setLines($any(count))\"\n >\n {{ count }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Linhas travadas em 2 para manter aderencia a referencia\n executiva.\n </p>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Skin</p>\n <div class=\"chip-row\">\n @for (option of skinOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'skin-' + option.id\"\n [class.is-active]=\"skin() === option.id\"\n (click)=\"setSkin(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Features mode</p>\n <div class=\"chip-row\">\n @for (option of featuresModeOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'features-' + option.id\"\n [class.is-active]=\"featuresMode() === option.id\"\n (click)=\"setFeaturesMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Selection</p>\n <div class=\"chip-row\">\n @for (option of selectionOptions; track option.id) {\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n [attr.data-testid]=\"'selection-' + option.id\"\n [class.is-active]=\"selectionMode() === option.id\"\n [disabled]=\"isExecutiveExpansionScenario()\"\n (click)=\"setSelectionMode(option.id)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n @if (isExecutiveExpansionScenario()) {\n <p class=\"control-hint\">\n Selecao desabilitada neste exemplo para evitar conflito com\n expansao por linha.\n </p>\n }\n </div>\n\n <div class=\"control-block\">\n <p class=\"control-block__title\">Customization mode</p>\n <div class=\"chip-row\">\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-on\"\n [class.is-active]=\"customizationEnabled()\"\n (click)=\"setCustomizationMode(true)\"\n >\n On\n </button>\n <button\n type=\"button\"\n class=\"chip-button chip-button--small\"\n data-testid=\"customization-off\"\n [class.is-active]=\"!customizationEnabled()\"\n (click)=\"setCustomizationMode(false)\"\n >\n Off\n </button>\n </div>\n <p class=\"control-hint\">\n Ative para exibir editor interno + AI assistant do componente.\n </p>\n </div>\n </article>\n\n <article class=\"panel panel--events\">\n <div class=\"panel__head\">\n <h2>Eventos</h2>\n <button\n type=\"button\"\n class=\"ghost-btn\"\n data-testid=\"clear-log\"\n (click)=\"clearLog()\"\n >\n Limpar log\n </button>\n </div>\n @if (eventLog().length === 0) {\n <p class=\"muted\">\n Sem eventos ainda. Clique em itens, acoes ou selecao.\n </p>\n } @else {\n <ul class=\"event-log\">\n @for (entry of eventLog(); track entry.id) {\n <li>{{ entry.message }}</li>\n }\n </ul>\n }\n </article>\n </aside>\n\n <article class=\"panel panel--live\">\n <h2>Exemplo live</h2>\n <p class=\"muted\">\n Mostra list/cards/tiles com os mesmos dados e configura em tempo real.\n </p>\n @if (scenario() === \"executive-expansion\") {\n <p class=\"muted\">\n Cenario canonico da V1 para validar linha executiva com detail row\n inline e owner de expansao dedicado.\n </p>\n }\n <praxis-list\n listId=\"praxis-list-doc-live\"\n componentInstanceId=\"main-showcase\"\n [config]=\"liveConfig()\"\n [form]=\"form\"\n [enableCustomization]=\"customizationEnabled()\"\n (itemClick)=\"handleItemClick($event)\"\n (actionClick)=\"handleActionClick($event)\"\n (selectionChange)=\"handleSelectionChange($event)\"\n />\n </article>\n </section>\n\n <section class=\"skin-matrix\">\n <div class=\"section-head\">\n <h2>Matriz de skins</h2>\n <p>\n Preview rapido de todos os estilos visuais disponiveis no componente.\n </p>\n </div>\n <div class=\"skin-matrix__grid\">\n @for (preview of skinPreviewConfigs(); track preview.type) {\n <article class=\"panel skin-preview\">\n <h3>{{ preview.type }}</h3>\n <praxis-list-skin-preview\n [config]=\"preview.config\"\n [items]=\"skinPreviewItems\"\n />\n </article>\n }\n </div>\n </section>\n\n <section class=\"code-lab panel\">\n <div class=\"section-head\">\n <h2>Snippets de referencia</h2>\n <p>\n Use os blocos abaixo para replicar os exemplos no host ou no site de\n documentacao.\n </p>\n </div>\n\n <div class=\"code-tabs\">\n @for (tab of codeTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"chip-button\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.is-active]=\"activeTab() === tab.id\"\n (click)=\"setCodeTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <pre class=\"code-box\"><code>{{ selectedSnippet() }}</code></pre>\n </section>\n\n <section class=\"notes panel\">\n <h2>Notas de arquitetura</h2>\n <ul>\n <li>\n <strong>Persistencia:</strong> sempre definir <code>listId</code>; para\n multiplas instancias, use <code>componentInstanceId</code>.\n </li>\n <li>\n <strong>Local vs remoto:</strong> <code>dataSource.data</code> tem\n precedencia para preview local; <code>resourcePath</code> define o\n contrato remoto.\n </li>\n <li>\n <strong>Toolbar remota:</strong> controles de paginacao/sort/busca\n refletem o contrato; a semantica completa de filtro/paginacao depende do\n backend em <code>/filter</code>.\n </li>\n <li>\n <strong>Editor interno:</strong> habilite\n <code>enableCustomization</code> quando o host tiver os providers de\n Settings Panel e AI.\n </li>\n <li>\n <strong>A11y:</strong> configure <code>a11y.ariaLabel</code>/<code\n >ariaLabelledBy</code\n >\n e mantenha labels de acoes explicitas.\n </li>\n <li>\n <strong>Expansao inline V1:</strong> suportada apenas em\n <code>layout.variant = list</code>.\n </li>\n <li>\n <strong>Selecao + expansao:</strong> quando houver selecao, o trigger\n canonico e por icone para evitar ambiguidade operacional.\n </li>\n </ul>\n </section>\n</section>\n", styles: [":host{display:block}.list-doc-page{--doc-bg: linear-gradient(160deg, #eef5ff 0%, #f9fbff 48%, #e8f7ef 100%);--doc-surface: rgba(255, 255, 255, .86);--doc-surface-strong: #ffffff;--doc-border: #cfdae8;--doc-text: #10243a;--doc-muted: #4d6075;--doc-accent: #0b6dff;--doc-accent-2: #0f9d58;--doc-accent-soft: color-mix(in srgb, var(--doc-accent) 15%, #ffffff);display:grid;gap:20px;padding:18px;border-radius:22px;border:1px solid var(--doc-border);color:var(--doc-text);background:var(--doc-bg);font-family:Manrope,Segoe UI,sans-serif}.hero{display:grid;gap:16px;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}.hero__copy{border-radius:18px;border:1px solid var(--doc-border);padding:18px;background:radial-gradient(120% 130% at 0% 0%,rgba(11,109,255,.2),transparent 56%),var(--doc-surface-strong);box-shadow:0 14px 24px #0a254c14}.hero__eyebrow{margin:0 0 8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#385f9c;font-weight:700}.hero h1{margin:0;font-size:clamp(1.24rem,2.8vw,1.86rem);line-height:1.25}.hero h1 code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 28%,#cad6ec);border-radius:8px;padding:2px 6px;font-size:.9em}.hero p{margin:10px 0 0;color:var(--doc-muted)}.hero__badges{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px}.hero__badges span{border-radius:999px;border:1px solid color-mix(in srgb,#0f9d58 26%,#cad9d2);background:color-mix(in srgb,#0f9d58 12%,#ffffff);color:#0f5d39;padding:5px 10px;font-size:12px;font-weight:700}.hero__panel{border-radius:18px;border:1px solid var(--doc-border);padding:16px;background:var(--doc-surface);box-shadow:0 10px 20px #182e5414}.hero__panel-title{margin:0 0 10px;font-size:13px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#345684}.hero__panel ul{margin:0;padding:0;list-style:none;display:grid;gap:8px}.hero__panel li{display:grid;gap:2px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,#274f82 14%,#d1d8e6);background:#fff}.hero__panel strong{font-size:12px}.hero__panel span{color:var(--doc-muted);font-size:12px}.lab{display:grid;gap:14px;grid-template-columns:minmax(200px,240px) minmax(0,1fr);align-items:start}.controls{display:grid;gap:12px}.panel{border-radius:16px;border:1px solid var(--doc-border);background:var(--doc-surface);box-shadow:0 8px 18px #1b2d4f12}.panel--controls,.panel--events{padding:14px}.panel--controls h2,.panel--live h2,.panel--events h2,.skin-preview h3,.code-lab h2,.notes h2{margin:0}.panel--live{padding:14px;min-width:0}.muted{margin:6px 0 0;color:var(--doc-muted);font-size:13px}.control-block{margin-top:12px}.control-grid{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr))}.control-block__title{margin:0 0 6px;font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#325d96}.control-hint{margin:8px 0 0;color:var(--doc-muted);font-size:12px}.chip-row{display:flex;gap:7px;flex-wrap:wrap}.chip-button{min-height:30px;border-radius:999px;border:1px solid color-mix(in srgb,#225ea9 30%,#c8d3e3);background:#f4f8ff;color:#1f3f69;padding:0 12px;font-size:12px;font-weight:700;cursor:pointer;transition:.14s ease;transition-property:border-color,background,color,transform}.chip-button--small{min-height:28px;padding-inline:10px;font-size:11px}.chip-button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--doc-accent) 44%,#a6bad7)}.chip-button.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#6f8aa9);background:linear-gradient(140deg,#1565d8,#0f9360);color:#fff}.chip-button:focus-visible,.ghost-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 65%,#416688);outline-offset:1px}.panel__head{display:flex;gap:10px;justify-content:space-between;align-items:center}.ghost-btn{min-height:30px;border-radius:8px;border:1px solid color-mix(in srgb,#173d6e 32%,#cdd7e4);background:#fff;color:#1f3d66;font-size:12px;font-weight:700;padding:0 10px;cursor:pointer}.event-log{margin:10px 0 0;padding:0;list-style:none;display:grid;gap:6px}.event-log li{border-radius:9px;border:1px solid color-mix(in srgb,#34598a 16%,#ccd7e6);background:#fff;padding:7px 9px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;color:#273e5f}.skin-matrix{display:grid;gap:10px}.section-head h2{margin:0}.section-head p{margin:4px 0 0;color:var(--doc-muted)}.skin-matrix__grid{display:grid;gap:12px;width:100%;max-width:1840px;margin-inline:auto;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}.skin-preview{padding:12px;min-width:0}.skin-preview h3{margin-bottom:8px;text-transform:capitalize}.code-lab{padding:14px}.code-tabs{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap}.code-box{margin:12px 0 0;border-radius:12px;border:1px solid color-mix(in srgb,#2d3f58 36%,#8194aa);background:#0d1420;color:#d9ecff;padding:12px;max-height:360px;overflow:auto;font-size:12px;line-height:1.55}.notes{padding:14px}.notes ul{margin:10px 0 0;padding-left:18px;display:grid;gap:8px}.notes li{color:#21354f}.notes code{background:color-mix(in srgb,#0b6dff 12%,#ffffff);border:1px solid color-mix(in srgb,#0b6dff 30%,#c8d5e7);border-radius:6px;padding:1px 5px}@media(max-width:1060px){.hero,.lab{grid-template-columns:1fr}}@media(max-width:700px){.list-doc-page{padding:12px}.control-grid{grid-template-columns:1fr}}\n"] }]
|
|
19993
20856
|
}] });
|
|
19994
20857
|
|
|
19995
20858
|
/*
|