@praxisui/list 8.0.0-beta.27 → 8.0.0-beta.29

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.
@@ -7,7 +7,7 @@ import * as i3 from '@angular/material/list';
7
7
  import { MatListModule } from '@angular/material/list';
8
8
  import * as i4 from '@angular/material/icon';
9
9
  import { MatIconModule } from '@angular/material/icon';
10
- import { resolveValuePresentation, LoggerService, GenericCrudService, toTitleCase, PraxisIconDirective, validateGlobalActionRefs, providePraxisI18n, PraxisI18nService, IconPickerService, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, SurfaceOpenActionEditorComponent, PRAXIS_I18N_CONFIG, providePraxisI18nConfig, SURFACE_OPEN_I18N_CONFIG, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, PraxisJsonLogicService, PraxisCollectionExportService, GlobalActionService, GLOBAL_DIALOG_SERVICE, assertPraxisCollectionExportArtifact, ComponentMetadataRegistry, API_URL, LocalStorageAsyncAdapter, LocalStorageConfigService } from '@praxisui/core';
10
+ import { resolveValuePresentation, LoggerService, GenericCrudService, toTitleCase, PraxisIconDirective, validateGlobalActionRefs, providePraxisI18n, PraxisI18nService, IconPickerService, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, SurfaceOpenActionEditorComponent, PRAXIS_I18N_CONFIG, providePraxisI18nConfig, SURFACE_OPEN_I18N_CONFIG, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, PraxisJsonLogicService, PraxisCollectionExportService, GlobalActionService, GLOBAL_DIALOG_SERVICE, assertPraxisCollectionExportArtifact, normalizePraxisDataQueryContext, ComponentMetadataRegistry, API_URL, LocalStorageAsyncAdapter, LocalStorageConfigService } from '@praxisui/core';
11
11
  import * as i5 from '@angular/material/chips';
12
12
  import { MatChipsModule } from '@angular/material/chips';
13
13
  import { MatDividerModule } from '@angular/material/divider';
@@ -134,8 +134,9 @@ function evalExpr(expr, ctx, options) {
134
134
  }
135
135
  /**
136
136
  * Evaluate a template definition with basic pipe support.
137
- * Supported pipes:
137
+ * Supported top-level pipes:
138
138
  * - bool:TrueLabel:FalseLabel (maps truthy/falsey values to provided labels)
139
+ * - map:key=Label,... (maps scalar values to labels)
139
140
  */
140
141
  function evaluateTemplate(def, item, options) {
141
142
  if (!def)
@@ -157,6 +158,9 @@ function evaluateTemplate(def, item, options) {
157
158
  const truthy = toBoolean(value);
158
159
  value = truthy ? (trueLabel ?? 'Sim') : (falseLabel ?? 'Não');
159
160
  }
161
+ if (name === 'map') {
162
+ value = mapValue(value, args);
163
+ }
160
164
  }
161
165
  const out = { type: def.type, value, class: def.class, style: def.style, color: def.color, variant: def.variant, props: def.props, imageAlt: def.imageAlt };
162
166
  if (def.badge?.expr) {
@@ -169,6 +173,9 @@ function evaluateTemplate(def, item, options) {
169
173
  const truthy = toBoolean(badgeVal);
170
174
  badgeVal = truthy ? (trueLabel ?? 'Sim') : (falseLabel ?? 'Não');
171
175
  }
176
+ if (name === 'map') {
177
+ badgeVal = mapValue(badgeVal, args);
178
+ }
172
179
  }
173
180
  out.badge = {
174
181
  value: badgeVal,
@@ -295,6 +302,11 @@ function parseMap(spec) {
295
302
  }
296
303
  return out;
297
304
  }
305
+ function mapValue(value, spec) {
306
+ const map = parseMap(spec);
307
+ const key = String(value ?? '').trim();
308
+ return map[key] ?? map[key.toLowerCase?.()] ?? map[key.toUpperCase?.()] ?? key;
309
+ }
298
310
  function resolveTemplatePresentation(type, params) {
299
311
  const listI18n = params.options?.i18n;
300
312
  const localization = listI18n?.localization ||
@@ -1388,7 +1400,7 @@ class PraxisListSkinPreviewComponent {
1388
1400
  className: [node.class, (node.variant || 'filled') === 'outlined' ? 'chip-outlined' : '']
1389
1401
  .filter(Boolean)
1390
1402
  .join(' '),
1391
- style: this.mergeStyleRecords(this.parseInlineStyle(this.chipStyle(node.color, node.variant)), this.parseInlineStyle(node.style)),
1403
+ style: this.mergeStyleRecords(this.parseInlineStyle(this.richChipStyle(node.color, node.variant)), this.parseInlineStyle(node.style)),
1392
1404
  },
1393
1405
  ];
1394
1406
  case 'text':
@@ -1440,16 +1452,10 @@ class PraxisListSkinPreviewComponent {
1440
1452
  }];
1441
1453
  }
1442
1454
  featureLabel(item, expr) {
1443
- // simple replacement using the same evaluator used internally
1444
- return String(expr || '').replace(/\$\{([^}]+)\}/g, (_, path) => {
1445
- try {
1446
- const value = path.split('.').reduce((acc, k) => (acc == null ? undefined : acc[k]), { item });
1447
- return value == null ? '' : String(value);
1448
- }
1449
- catch {
1450
- return '';
1451
- }
1452
- });
1455
+ const expression = String(expr || '').trim();
1456
+ if (!expression)
1457
+ return '';
1458
+ return (evaluateTemplate({ type: 'text', expr: expression }, item, this.templateEvaluatorOptions())?.value ?? '');
1453
1459
  }
1454
1460
  featuresVisible() {
1455
1461
  const t = this.config?.templating;
@@ -1485,8 +1491,10 @@ class PraxisListSkinPreviewComponent {
1485
1491
  try {
1486
1492
  const map = this.config?.templating?.chipColorMap;
1487
1493
  if (map && typeof value === 'string') {
1494
+ const status = String(item?.status ?? '').trim();
1488
1495
  const key = String(value).toLowerCase();
1489
- const found = map[key] ?? map[value];
1496
+ const statusKey = status.toLowerCase();
1497
+ const found = map[key] ?? map[value] ?? map[statusKey] ?? map[status];
1490
1498
  if (found)
1491
1499
  color = found;
1492
1500
  }
@@ -1574,6 +1582,14 @@ class PraxisListSkinPreviewComponent {
1574
1582
  }
1575
1583
  return `background:${color}; color: var(--md-sys-color-on-primary);`;
1576
1584
  }
1585
+ richChipStyle(color, variant) {
1586
+ if (!color || this.isThemeColor(color))
1587
+ return '';
1588
+ if (variant === 'outlined') {
1589
+ return `--p-list-chip-color:${color}; --p-list-chip-border-color:${color}; --p-list-chip-background: transparent;`;
1590
+ }
1591
+ return `--p-list-chip-background:${color}; --p-list-chip-color: var(--md-sys-color-on-primary);`;
1592
+ }
1577
1593
  iconStyle(color) {
1578
1594
  if (!color || this.isThemeColor(color))
1579
1595
  return '';
@@ -1632,7 +1648,7 @@ class PraxisListSkinPreviewComponent {
1632
1648
  // trackBy for preview lists
1633
1649
  trackByIndex = (i) => i;
1634
1650
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisListSkinPreviewComponent, deps: [{ token: ListSkinService }], target: i0.ɵɵFactoryTarget.Component });
1635
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisListSkinPreviewComponent, isStandalone: true, selector: "praxis-list-skin-preview", inputs: { config: "config", items: "items", theme: "theme" }, ngImport: i0, template: "<div class=\"preview-root\" [ngClass]=\"skinClasses\" [attr.data-skin-scope]=\"skinScopeId\">\n @if (inlineCss) { <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style> }\n\n @if (isList()) {\n <mat-list>\n @for (item of items; track trackByIndex($index)) {\n <mat-list-item>\n <div class=\"list-item-content\">\n @if (leading(item); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div>\n <div class=\"primary\" [ngClass]=\"primary(item)?.class\" [style.cssText]=\"primary(item)?.style\">\n @if (previewRichContentNodes(primary(item)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(item)?.class\" [style.cssText]=\"secondary(item)?.style\">\n @if (previewRichContentNodes(secondary(item)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(item, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(item); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(item); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else if (isTiles()) {\n <div class=\"tiles-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-tile\">\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('image') {\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n }\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n </div>\n @if (trailing(it); as tr) {\n @if (statusPosition() === 'top-right' && (tr?.type === 'chip' || tr?.type === 'icon')) {\n <div class=\"tile-status\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === 'chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @if (tr?.type === 'icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n }\n </div>\n }\n }\n <div class=\"tile-body\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n </div>\n }\n @if (trailing(it); as tr2) {\n @if (!(statusPosition() === 'top-right' && (tr2?.type === 'chip' || tr2?.type === 'icon'))) {\n <div class=\"meta\" [ngClass]=\"tr2.class\" [style.cssText]=\"tr2.style\">\n @if (previewRichContentNodes(tr2); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr2.color) ? tr2.color : undefined\" [ngClass]=\"((tr2.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr2.color, tr2.variant)\">{{ tr2.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(tr2); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr2.value)\" [color]=\"ratingThemeColor(tr2)\" [style.cssText]=\"ratingIconStyle(tr2)\"></mat-icon> } }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr2.value\" [alt]=\"tr2.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"tr2.value\"></span> }\n @default { <span>{{ tr2.value }}</span> }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"cards-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div>\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(it); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".preview-root{--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-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-grad-foreground: var(--md-sys-color-on-primary);--p-list-grad-foreground-muted: var(--md-sys-color-on-primary);--p-list-surface: var(--md-sys-color-surface-container);--p-list-accent: var(--md-sys-color-primary);--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--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-tile-minW: 240px;--p-list-tile-gap: 16px;--p-list-tile-padding: 16px;--p-list-tile-radius: 16px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;padding:12px}.preview-light{background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface))}.preview-dark{background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.preview-grid{background-color:var(--md-sys-color-surface-variant, var(--md-sys-color-surface));background-image:linear-gradient(var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px),linear-gradient(90deg,var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px);background-size:16px 16px}.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)}.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}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:var(--p-list-foreground-muted)}.feature{display:inline-flex;align-items:center;gap:6px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted)}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile,.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.list-item-content{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;padding:12px 16px}.primary{font-weight:500;color:var(--p-list-foreground)}.secondary,.meta{color:var(--p-list-foreground-muted)}.trailing{color:var(--p-list-foreground-muted);text-align:end}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-card{padding:12px}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-tile{padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);border:var(--p-list-border);background:var(--p-list-surface);display:grid;gap:8px}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover}.tile-body{display:grid;gap:4px}.chip-outlined.mat-mdc-chip{background:transparent!important;border:1px solid currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5.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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1651
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisListSkinPreviewComponent, isStandalone: true, selector: "praxis-list-skin-preview", inputs: { config: "config", items: "items", theme: "theme" }, ngImport: i0, template: "<div class=\"preview-root\" [ngClass]=\"skinClasses\" [attr.data-skin-scope]=\"skinScopeId\">\n @if (inlineCss) { <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style> }\n\n @if (isList()) {\n <mat-list>\n @for (item of items; track trackByIndex($index)) {\n <mat-list-item>\n <div class=\"list-item-content\">\n @if (leading(item); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div class=\"list-item-text\">\n <div class=\"primary\" [ngClass]=\"primary(item)?.class\" [style.cssText]=\"primary(item)?.style\">\n @if (primary(item)?.type === 'html') {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else if (previewRichContentNodes(primary(item)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(item)?.class\" [style.cssText]=\"secondary(item)?.style\">\n @if (secondary(item)?.type === 'html') {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(item)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(item, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(item); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(item); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else if (isTiles()) {\n <div class=\"tiles-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-tile\">\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('image') {\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n }\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n </div>\n @if (trailing(it); as tr) {\n @if (statusPosition() === 'top-right' && (tr?.type === 'chip' || tr?.type === 'icon')) {\n <div class=\"tile-status\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === 'chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @if (tr?.type === 'icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n }\n </div>\n }\n }\n <div class=\"tile-body\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (primary(it)?.type === 'html') {\n <span [innerHTML]=\"primary(it)?.value\"></span>\n } @else if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (secondary(it)?.type === 'html') {\n <span [innerHTML]=\"secondary(it)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n </div>\n }\n @if (trailing(it); as tr2) {\n @if (!(statusPosition() === 'top-right' && (tr2?.type === 'chip' || tr2?.type === 'icon'))) {\n <div class=\"meta\" [ngClass]=\"tr2.class\" [style.cssText]=\"tr2.style\">\n @if (previewRichContentNodes(tr2); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr2.color) ? tr2.color : undefined\" [ngClass]=\"((tr2.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr2.color, tr2.variant)\">{{ tr2.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(tr2); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr2.value)\" [color]=\"ratingThemeColor(tr2)\" [style.cssText]=\"ratingIconStyle(tr2)\"></mat-icon> } }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr2.value\" [alt]=\"tr2.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"tr2.value\"></span> }\n @default { <span>{{ tr2.value }}</span> }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"cards-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div class=\"list-item-text\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (primary(it)?.type === 'html') {\n <span [innerHTML]=\"primary(it)?.value\"></span>\n } @else if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (secondary(it)?.type === 'html') {\n <span [innerHTML]=\"secondary(it)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(it); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".preview-root{--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-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--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-surface: var(--md-sys-color-surface-container);--p-list-accent: var(--md-sys-color-primary);--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--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-tile-minW: 240px;--p-list-tile-gap: 16px;--p-list-tile-padding: 16px;--p-list-tile-radius: 16px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;padding:12px;border-radius:12px;overflow:hidden}.preview-light{background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface))}.preview-dark{background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.preview-grid{background-color:var(--md-sys-color-surface-variant, var(--md-sys-color-surface));background-image:linear-gradient(var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px),linear-gradient(90deg,var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px);background-size:16px 16px}.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)}.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}.features{display:flex;flex-wrap:wrap;gap:8px;margin-top:2px;color:var(--p-list-foreground-muted);min-width:0}.feature{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;font-size:.75rem;line-height:1.25}.feature mat-icon{flex:0 0 auto;width:16px;height:16px;font-size:16px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted)}.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.list-item-content{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;padding:12px 16px;min-width:0}.primary{font-weight:600;color:var(--p-list-foreground);min-width:0;overflow:hidden;text-overflow:ellipsis}.secondary{color:var(--p-list-foreground-muted);min-width:0;overflow:hidden}.meta{color:var(--p-list-foreground-muted);min-width:0}.trailing{color:var(--p-list-foreground-muted);text-align:end;min-width:0}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-card{position:relative;display:grid;min-height:236px;padding:10px;overflow:hidden;color:var(--p-list-foreground)}.item-card .list-item-content{display:block;grid-template-columns:minmax(0,1fr);align-items:stretch;gap:8px;padding:0;min-width:0;overflow:hidden}.item-card .list-item-text{display:grid;gap:8px;min-width:0;width:100%}.item-card .lead-image{width:100%;height:auto;aspect-ratio:16/9;max-height:104px;border-radius:10px}.item-card .lead-image .lead-badge{max-width:calc(100% - 16px)}.item-card .primary{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-height:1.28;min-width:0;overflow-wrap:anywhere}.item-card .secondary{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;font-size:.78rem;line-height:1.3;color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent);min-width:0;overflow-wrap:anywhere}.item-card .meta{display:inline-flex;align-items:center;gap:2px;max-width:100%;overflow:hidden;white-space:nowrap;font-size:.76rem;line-height:1.2;color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent)}.item-card .meta mat-icon{flex:0 0 auto;width:16px;height:16px;font-size:16px}.item-card .trailing{justify-self:start;max-width:100%;text-align:start;color:inherit}.item-card .features{color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent);min-width:0}.item-card .feature{min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .mat-mdc-chip{max-width:100%}.preview-root ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}.preview-root ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:1px 9px;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}.item-card .mdc-evolution-chip__text-label,.item-card [data-rich-node-type=badge]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-tile{padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);border:var(--p-list-border);background:var(--p-list-surface);display:grid;gap:8px}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover}.tile-body{display:grid;gap:4px}.chip-outlined.mat-mdc-chip{background:transparent!important;border:1px solid currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5.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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1636
1652
  }
1637
1653
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisListSkinPreviewComponent, decorators: [{
1638
1654
  type: Component,
@@ -1643,7 +1659,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
1643
1659
  MatChipsModule,
1644
1660
  PraxisIconDirective,
1645
1661
  PraxisRichContent,
1646
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"preview-root\" [ngClass]=\"skinClasses\" [attr.data-skin-scope]=\"skinScopeId\">\n @if (inlineCss) { <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style> }\n\n @if (isList()) {\n <mat-list>\n @for (item of items; track trackByIndex($index)) {\n <mat-list-item>\n <div class=\"list-item-content\">\n @if (leading(item); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div>\n <div class=\"primary\" [ngClass]=\"primary(item)?.class\" [style.cssText]=\"primary(item)?.style\">\n @if (previewRichContentNodes(primary(item)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(item)?.class\" [style.cssText]=\"secondary(item)?.style\">\n @if (previewRichContentNodes(secondary(item)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(item, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(item); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(item); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else if (isTiles()) {\n <div class=\"tiles-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-tile\">\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('image') {\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n }\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n </div>\n @if (trailing(it); as tr) {\n @if (statusPosition() === 'top-right' && (tr?.type === 'chip' || tr?.type === 'icon')) {\n <div class=\"tile-status\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === 'chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @if (tr?.type === 'icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n }\n </div>\n }\n }\n <div class=\"tile-body\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n </div>\n }\n @if (trailing(it); as tr2) {\n @if (!(statusPosition() === 'top-right' && (tr2?.type === 'chip' || tr2?.type === 'icon'))) {\n <div class=\"meta\" [ngClass]=\"tr2.class\" [style.cssText]=\"tr2.style\">\n @if (previewRichContentNodes(tr2); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr2.color) ? tr2.color : undefined\" [ngClass]=\"((tr2.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr2.color, tr2.variant)\">{{ tr2.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(tr2); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr2.value)\" [color]=\"ratingThemeColor(tr2)\" [style.cssText]=\"ratingIconStyle(tr2)\"></mat-icon> } }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr2.value\" [alt]=\"tr2.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"tr2.value\"></span> }\n @default { <span>{{ tr2.value }}</span> }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"cards-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div>\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(it); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".preview-root{--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-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--p-list-grad-foreground: var(--md-sys-color-on-primary);--p-list-grad-foreground-muted: var(--md-sys-color-on-primary);--p-list-surface: var(--md-sys-color-surface-container);--p-list-accent: var(--md-sys-color-primary);--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--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-tile-minW: 240px;--p-list-tile-gap: 16px;--p-list-tile-padding: 16px;--p-list-tile-radius: 16px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;padding:12px}.preview-light{background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface))}.preview-dark{background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.preview-grid{background-color:var(--md-sys-color-surface-variant, var(--md-sys-color-surface));background-image:linear-gradient(var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px),linear-gradient(90deg,var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px);background-size:16px 16px}.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)}.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}.features{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:var(--p-list-foreground-muted)}.feature{display:inline-flex;align-items:center;gap:6px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted)}.skin-gradient-tile .item-card,.skin-gradient-tile .item-tile,.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.list-item-content{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;padding:12px 16px}.primary{font-weight:500;color:var(--p-list-foreground)}.secondary,.meta{color:var(--p-list-foreground-muted)}.trailing{color:var(--p-list-foreground-muted);text-align:end}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-card{padding:12px}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-tile{padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);border:var(--p-list-border);background:var(--p-list-surface);display:grid;gap:8px}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover}.tile-body{display:grid;gap:4px}.chip-outlined.mat-mdc-chip{background:transparent!important;border:1px solid currentColor}\n"] }]
1662
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"preview-root\" [ngClass]=\"skinClasses\" [attr.data-skin-scope]=\"skinScopeId\">\n @if (inlineCss) { <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style> }\n\n @if (isList()) {\n <mat-list>\n @for (item of items; track trackByIndex($index)) {\n <mat-list-item>\n <div class=\"list-item-content\">\n @if (leading(item); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div class=\"list-item-text\">\n <div class=\"primary\" [ngClass]=\"primary(item)?.class\" [style.cssText]=\"primary(item)?.style\">\n @if (primary(item)?.type === 'html') {\n <span [innerHTML]=\"primary(item)?.value\"></span>\n } @else if (previewRichContentNodes(primary(item)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(item)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(item)?.class\" [style.cssText]=\"secondary(item)?.style\">\n @if (secondary(item)?.type === 'html') {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(item)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(item)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(item, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(item); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(item); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </mat-list-item>\n }\n </mat-list>\n } @else if (isTiles()) {\n <div class=\"tiles-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-tile\">\n <div class=\"tile-media\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('image') {\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n }\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n </div>\n @if (trailing(it); as tr) {\n @if (statusPosition() === 'top-right' && (tr?.type === 'chip' || tr?.type === 'icon')) {\n <div class=\"tile-status\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === 'chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @if (tr?.type === 'icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n }\n </div>\n }\n }\n <div class=\"tile-body\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (primary(it)?.type === 'html') {\n <span [innerHTML]=\"primary(it)?.value\"></span>\n } @else if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (secondary(it)?.type === 'html') {\n <span [innerHTML]=\"secondary(it)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (featuresVisible()) {\n <div class=\"features\">\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n </div>\n }\n @if (trailing(it); as tr2) {\n @if (!(statusPosition() === 'top-right' && (tr2?.type === 'chip' || tr2?.type === 'icon'))) {\n <div class=\"meta\" [ngClass]=\"tr2.class\" [style.cssText]=\"tr2.style\">\n @if (previewRichContentNodes(tr2); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr2.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr2.color) ? tr2.color : undefined\" [ngClass]=\"((tr2.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr2.color, tr2.variant)\">{{ tr2.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(tr2); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr2.value)\" [color]=\"ratingThemeColor(tr2)\" [style.cssText]=\"ratingIconStyle(tr2)\"></mat-icon> } }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr2.value\" [alt]=\"tr2.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"tr2.value\"></span> }\n @default { <span>{{ tr2.value }}</span> }\n }\n }\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"cards-grid\">\n @for (it of items; track trackByIndex($index)) {\n <div class=\"item-card\">\n <div class=\"list-item-content\">\n @if (leading(it); as lead) {\n @if (previewRichContentNodes(lead, { imageAlt: config.templating?.leading?.imageAlt }); as leadNodes) {\n <praxis-rich-content [nodes]=\"leadNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case ('icon') { <mat-icon [praxisIcon]=\"lead.value\" [ngClass]=\"lead.class\" [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [style.cssText]=\"(lead.style ? lead.style + ';' : '') + iconStyle(lead.color)\"></mat-icon> }\n @case ('image') {\n <div class=\"lead-image\" [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\n <img [src]=\"lead.value\" [alt]=\"config.templating?.leading?.imageAlt || ''\" />\n @if (lead.badge?.value) { <mat-chip class=\"lead-badge\"\n [color]=\"isThemeColor(lead.badge?.color) ? lead.badge?.color : undefined\"\n [ngClass]=\"(((lead.badge?.variant || 'filled') === 'outlined') ? 'chip-outlined' : '')\"\n [style.cssText]=\"chipStyle(lead.badge?.color, lead.badge?.variant)\">{{ lead.badge?.value }}</mat-chip> }\n </div>\n }\n @case ('text') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n @case ('chip') { <mat-chip [color]=\"isThemeColor(lead.color) ? lead.color : undefined\" [ngClass]=\"((lead.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(lead.color, lead.variant)\">{{ lead.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(lead); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, lead.value)\" [color]=\"ratingThemeColor(lead)\" [style.cssText]=\"ratingIconStyle(lead)\"></mat-icon> } }\n @case ('html') { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\" [innerHTML]=\"lead.value\"></span> }\n @default { <span [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{ lead.value }}</span> }\n }\n }\n }\n <div class=\"list-item-text\">\n <div class=\"primary\" [ngClass]=\"primary(it)?.class\" [style.cssText]=\"primary(it)?.style\">\n @if (primary(it)?.type === 'html') {\n <span [innerHTML]=\"primary(it)?.value\"></span>\n } @else if (previewRichContentNodes(primary(it)); as primaryNodes) {\n <praxis-rich-content [nodes]=\"primaryNodes\"></praxis-rich-content>\n } @else {\n {{ primary(it)?.value }}\n }\n </div>\n @if ((config.layout?.lines || 1) > 1) {\n <div class=\"secondary\" [ngClass]=\"secondary(it)?.class\" [style.cssText]=\"secondary(it)?.style\">\n @if (secondary(it)?.type === 'html') {\n <span [innerHTML]=\"secondary(it)?.value\"></span>\n } @else if (previewRichContentNodes(secondary(it)); as secondaryNodes) {\n <praxis-rich-content [nodes]=\"secondaryNodes\"></praxis-rich-content>\n } @else {\n {{ secondary(it)?.value }}\n }\n </div>\n }\n @if (featuresVisible()) {\n @for (f of (config.templating?.features || []); track $index; let fi = $index) {\n <span class=\"feature\">\n @if (previewFeatureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== 'labels-only') { <mat-icon [praxisIcon]=\"f.icon\"></mat-icon> }\n @if (featuresMode() !== 'icons-only') { <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">{{ featureLabel(it, f.expr) }}</span> }\n }\n </span>\n }\n }\n </div>\n @if (meta(it); as m) {\n <div class=\"meta\" [ngClass]=\"m.class\" [style.cssText]=\"m.style\">\n @if (metaPrefixIcon(); as mpi) { <mat-icon [praxisIcon]=\"mpi\"></mat-icon> }\n @if (previewRichContentNodes(m, { slot: 'meta' }); as metaNodes) {\n <praxis-rich-content [nodes]=\"metaNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(m.color) ? m.color : undefined\" [ngClass]=\"((m.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(m.color, m.variant)\">{{ m.value }}</mat-chip> }\n @case ('rating') { @for (_ of ratingRange(m); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, m.value)\" [color]=\"ratingThemeColor(m)\" [style.cssText]=\"ratingIconStyle(m)\"></mat-icon> } }\n @case ('icon') { <mat-icon [praxisIcon]=\"m.value\" [color]=\"isThemeColor(m.color) ? m.color : undefined\" [style.cssText]=\"iconStyle(m.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"m.value\" [alt]=\"m.imageAlt || ''\" /></span> }\n @case ('html') { <span [innerHTML]=\"m.value\"></span> }\n @default { <span>{{ m.value }}</span> }\n }\n }\n </div>\n }\n @if (trailing(it); as tr) {\n <div class=\"trailing\" [ngClass]=\"tr.class\" [style.cssText]=\"tr.style\">\n @if (previewRichContentNodes(tr); as trailingNodes) {\n <praxis-rich-content [nodes]=\"trailingNodes\"></praxis-rich-content>\n } @else {\n @switch (tr.type) {\n @case ('chip') { <mat-chip [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [ngClass]=\"((tr.variant || 'filled') === 'outlined') ? 'chip-outlined' : ''\" [style.cssText]=\"chipStyle(tr.color, tr.variant)\">{{ tr.value }}</mat-chip> }\n @case ('icon') { <mat-icon [praxisIcon]=\"tr.value\" [color]=\"isThemeColor(tr.color) ? tr.color : undefined\" [style.cssText]=\"iconStyle(tr.color)\"></mat-icon> }\n @case ('image') { <span class=\"inline-image\"><img [src]=\"tr.value\" [alt]=\"tr.imageAlt || ''\" /></span> }\n @case ('rating') { @for (_ of ratingRange(tr); track $index; let idx = $index) { <mat-icon [praxisIcon]=\"starIcon(idx, tr.value)\" [color]=\"ratingThemeColor(tr)\" [style.cssText]=\"ratingIconStyle(tr)\"></mat-icon> } }\n @case ('html') { <span [innerHTML]=\"tr.value\"></span> }\n @default { <span>{{ tr.value }}</span> }\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".preview-root{--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-foreground: var(--md-sys-color-on-surface);--p-list-foreground-muted: var(--md-sys-color-on-surface-variant);--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-surface: var(--md-sys-color-surface-container);--p-list-accent: var(--md-sys-color-primary);--p-list-item-border: 1px solid var(--md-sys-color-outline-variant);--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-tile-minW: 240px;--p-list-tile-gap: 16px;--p-list-tile-padding: 16px;--p-list-tile-radius: 16px;--p-list-tile-media-radius: 12px;--p-list-tile-media-ratio: 1 / 1;padding:12px;border-radius:12px;overflow:hidden}.preview-light{background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface))}.preview-dark{background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.preview-grid{background-color:var(--md-sys-color-surface-variant, var(--md-sys-color-surface));background-image:linear-gradient(var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px),linear-gradient(90deg,var(--md-sys-color-outline-variant, var(--md-sys-color-outline)) 1px,transparent 1px);background-size:16px 16px}.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)}.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}.features{display:flex;flex-wrap:wrap;gap:8px;margin-top:2px;color:var(--p-list-foreground-muted);min-width:0}.feature{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;font-size:.75rem;line-height:1.25}.feature mat-icon{flex:0 0 auto;width:16px;height:16px;font-size:16px}.model-media .lead-image{width:136px;height:96px;border-radius:16px}.model-hotel .lead-image{width:160px;height:110px;border-radius:18px}.skin-gradient-tile{--p-list-foreground: var(--p-list-grad-foreground);--p-list-foreground-muted: var(--p-list-grad-foreground-muted)}.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);backdrop-filter:blur(var(--p-list-blur));-webkit-backdrop-filter:blur(var(--p-list-blur));color:var(--p-list-foreground)}.list-item-content{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;padding:12px 16px;min-width:0}.primary{font-weight:600;color:var(--p-list-foreground);min-width:0;overflow:hidden;text-overflow:ellipsis}.secondary{color:var(--p-list-foreground-muted);min-width:0;overflow:hidden}.meta{color:var(--p-list-foreground-muted);min-width:0}.trailing{color:var(--p-list-foreground-muted);text-align:end;min-width:0}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-card{position:relative;display:grid;min-height:236px;padding:10px;overflow:hidden;color:var(--p-list-foreground)}.item-card .list-item-content{display:block;grid-template-columns:minmax(0,1fr);align-items:stretch;gap:8px;padding:0;min-width:0;overflow:hidden}.item-card .list-item-text{display:grid;gap:8px;min-width:0;width:100%}.item-card .lead-image{width:100%;height:auto;aspect-ratio:16/9;max-height:104px;border-radius:10px}.item-card .lead-image .lead-badge{max-width:calc(100% - 16px)}.item-card .primary{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-height:1.28;min-width:0;overflow-wrap:anywhere}.item-card .secondary{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;font-size:.78rem;line-height:1.3;color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent);min-width:0;overflow-wrap:anywhere}.item-card .meta{display:inline-flex;align-items:center;gap:2px;max-width:100%;overflow:hidden;white-space:nowrap;font-size:.76rem;line-height:1.2;color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent)}.item-card .meta mat-icon{flex:0 0 auto;width:16px;height:16px;font-size:16px}.item-card .trailing{justify-self:start;max-width:100%;text-align:start;color:inherit}.item-card .features{color:color-mix(in srgb,var(--p-list-foreground) 72%,transparent);min-width:0}.item-card .feature{min-width:0;max-width:100%;overflow-wrap:anywhere}.item-card .mat-mdc-chip{max-width:100%}.preview-root ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=badge]{background:transparent;color:inherit}.preview-root ::ng-deep praxis-rich-content .prx-rich-node[data-rich-node-type=badge] .prx-rich-badge{min-height:22px;padding:1px 9px;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}.item-card .mdc-evolution-chip__text-label,.item-card [data-rich-node-type=badge]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--p-list-tile-minW),1fr));gap:var(--p-list-tile-gap)}.item-tile{padding:var(--p-list-tile-padding);border-radius:var(--p-list-tile-radius);border:var(--p-list-border);background:var(--p-list-surface);display:grid;gap:8px}.tile-media{width:100%;aspect-ratio:var(--p-list-tile-media-ratio);border-radius:var(--p-list-tile-media-radius);background:var(--md-sys-color-surface-container-low, var(--p-list-surface));display:grid;place-items:center;overflow:hidden}.tile-media img{width:100%;height:100%;object-fit:cover}.tile-body{display:grid;gap:4px}.chip-outlined.mat-mdc-chip{background:transparent!important;border:1px solid currentColor}\n"] }]
1647
1663
  }], ctorParameters: () => [{ type: ListSkinService }], propDecorators: { config: [{
1648
1664
  type: Input
1649
1665
  }], items: [{
@@ -2188,8 +2204,8 @@ function validateListAuthoringDocument(doc, context) {
2188
2204
  validateRawRules(diagnostics, asRecord(rawConfig.rules), 'config.rules');
2189
2205
  validateRawExpansion(diagnostics, rawExpansion, 'config.expansion');
2190
2206
  if (config.interaction?.expandable) {
2191
- if (config.layout?.variant !== 'list') {
2192
- diagnostics.push(errorDiagnostic('list.interaction.expandable.variant.unsupported', 'config.interaction.expandable currently supports only config.layout.variant = list', 'config.interaction.expandable'));
2207
+ if (config.layout?.variant === 'tiles') {
2208
+ diagnostics.push(errorDiagnostic('list.interaction.expandable.variant.unsupported', 'config.interaction.expandable currently supports config.layout.variant = list or cards', 'config.interaction.expandable'));
2193
2209
  }
2194
2210
  if ((config.expansion?.sections?.length || 0) === 0) {
2195
2211
  diagnostics.push(errorDiagnostic('list.expansion.sections.required', 'config.expansion.sections is required when config.interaction.expandable is true', 'config.expansion.sections'));
@@ -11159,6 +11175,19 @@ const ROW_LAYOUT_SUPPORTED_SLOTS = [
11159
11175
  'actions',
11160
11176
  'expand',
11161
11177
  ];
11178
+ const CARD_DETAIL_SLOT_LABELS = {
11179
+ identity: 'Identidade',
11180
+ balance: 'Valor liquido',
11181
+ limit: 'Descontos',
11182
+ risk: 'Composicao',
11183
+ alerts: 'Alertas',
11184
+ owner: 'Responsavel',
11185
+ };
11186
+ const CARD_DETAIL_DEFAULT_SLOTS = [
11187
+ 'balance',
11188
+ 'limit',
11189
+ 'risk',
11190
+ ];
11162
11191
  class PraxisList {
11163
11192
  static nextSkinScopeId = 0;
11164
11193
  customizationEnabled = false;
@@ -11167,6 +11196,7 @@ class PraxisList {
11167
11196
  listId;
11168
11197
  componentInstanceId;
11169
11198
  configPersistenceStrategy = 'local-first';
11199
+ queryContext;
11170
11200
  form;
11171
11201
  set enableCustomization(value) {
11172
11202
  this.customizationEnabled = value;
@@ -11184,6 +11214,7 @@ class PraxisList {
11184
11214
  total$;
11185
11215
  page$;
11186
11216
  lastQuery = {};
11217
+ lastRuntimeQueryContextSignature = '';
11187
11218
  search$ = new Subject();
11188
11219
  get layoutLines() {
11189
11220
  return this.config?.layout?.lines ?? 2;
@@ -11288,6 +11319,7 @@ class PraxisList {
11288
11319
  this.syncPaginatorIntl();
11289
11320
  this.initializeDataStreams();
11290
11321
  this.applyAuthoringPayload(this.config, 'external-input');
11322
+ this.applyRuntimeQueryContext();
11291
11323
  this.setupSearch();
11292
11324
  this.applyPersistence();
11293
11325
  }
@@ -11313,8 +11345,12 @@ class PraxisList {
11313
11345
  this.externalConfigRevision += 1;
11314
11346
  this.applyAuthoringPayload(changes['config'].currentValue, 'external-input');
11315
11347
  this.syncPaginatorIntl();
11348
+ this.applyRuntimeQueryContext();
11316
11349
  }
11317
11350
  }
11351
+ if (changes['queryContext']) {
11352
+ this.applyRuntimeQueryContext();
11353
+ }
11318
11354
  if (shouldApplyPersistence) {
11319
11355
  this.applyPersistence();
11320
11356
  }
@@ -11551,9 +11587,9 @@ class PraxisList {
11551
11587
  return this.joinClasses('list-row-slot', `list-row-slot--${this.sanitizeCssToken(column.slot)}`, column.class);
11552
11588
  }
11553
11589
  rowLayoutColumnStyle(column) {
11554
- return this.joinStyles(column.minWidth ? `min-width:${column.minWidth};` : undefined, column.maxWidth ? `max-width:${column.maxWidth};` : undefined, column.justify ? `justify-self:${column.justify};` : undefined, (column.align || this.rowLayoutAlignItems()) &&
11555
- (column.align || this.rowLayoutAlignItems()) !== 'stretch'
11556
- ? `align-self:${column.align || this.rowLayoutAlignItems()};`
11590
+ const align = column.align || this.rowLayoutAlignItems();
11591
+ return this.joinStyles(column.minWidth ? `min-width:${column.minWidth};` : undefined, column.maxWidth ? `max-width:${column.maxWidth};` : undefined, column.justify ? `justify-self:${column.justify};` : undefined, align === 'stretch' ? 'align-self:stretch;' : undefined, align && align !== 'stretch'
11592
+ ? this.cssVar('--p-list-row-slot-align-items', align)
11557
11593
  : undefined, this.rowLayoutTextAlign(column.justify), column.style);
11558
11594
  }
11559
11595
  rowLayoutSlot(item, slot) {
@@ -11584,6 +11620,49 @@ class PraxisList {
11584
11620
  return null;
11585
11621
  }
11586
11622
  }
11623
+ cardDetailSlots(item) {
11624
+ const rowLayoutSlots = this.rowLayoutColumns()
11625
+ .map((column) => column.slot)
11626
+ .filter((slot) => slot !== 'leading' &&
11627
+ slot !== 'primary' &&
11628
+ slot !== 'secondary' &&
11629
+ slot !== 'meta' &&
11630
+ slot !== 'trailing' &&
11631
+ slot !== 'identity' &&
11632
+ slot !== 'actions' &&
11633
+ slot !== 'expand');
11634
+ const slots = Array.from(new Set([
11635
+ ...rowLayoutSlots,
11636
+ ...CARD_DETAIL_DEFAULT_SLOTS,
11637
+ ]));
11638
+ return slots
11639
+ .map((slot) => ({
11640
+ slot,
11641
+ label: CARD_DETAIL_SLOT_LABELS[slot] || this.humanizeSlotLabel(slot),
11642
+ node: this.rowLayoutSlot(item, slot),
11643
+ }))
11644
+ .filter((detail) => !!detail.node && this.hasDisplayableNodeValue(detail.node));
11645
+ }
11646
+ humanizeSlotLabel(slot) {
11647
+ return slot
11648
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
11649
+ .replace(/[-_]+/g, ' ')
11650
+ .replace(/\s+/g, ' ')
11651
+ .trim()
11652
+ .replace(/^./, (char) => char.toUpperCase());
11653
+ }
11654
+ hasDisplayableNodeValue(node) {
11655
+ if (node.type === 'compose') {
11656
+ return (Array.isArray(node.items) &&
11657
+ node.items.some((child) => this.hasDisplayableNodeValue(child)));
11658
+ }
11659
+ const value = node.value;
11660
+ if (Array.isArray(value))
11661
+ return value.length > 0;
11662
+ if (value === null || value === undefined)
11663
+ return false;
11664
+ return String(value).trim().length > 0;
11665
+ }
11587
11666
  rowLayoutHasSlot(slot) {
11588
11667
  return this.rowLayoutColumns().some((column) => column.slot === slot);
11589
11668
  }
@@ -12897,6 +12976,34 @@ class PraxisList {
12897
12976
  });
12898
12977
  this.executeListEditorApplyPlan(plan, doc, trigger);
12899
12978
  }
12979
+ applyRuntimeQueryContext() {
12980
+ this.initializeDataStreams();
12981
+ const normalized = normalizePraxisDataQueryContext(this.queryContext);
12982
+ const baseQuery = this.config?.dataSource?.query || {};
12983
+ const nextQuery = {
12984
+ ...baseQuery,
12985
+ ...(normalized?.filters || {}),
12986
+ };
12987
+ const pageSize = normalized?.page?.size ?? normalized?.limit ?? null;
12988
+ const pageIndex = normalized?.page?.index ?? 0;
12989
+ const signature = JSON.stringify({
12990
+ query: nextQuery,
12991
+ sort: normalized?.sort || null,
12992
+ pageSize,
12993
+ pageIndex,
12994
+ });
12995
+ if (signature === this.lastRuntimeQueryContextSignature)
12996
+ return;
12997
+ this.lastRuntimeQueryContextSignature = signature;
12998
+ this.lastQuery = nextQuery;
12999
+ this.data.setQuery(nextQuery);
13000
+ if (normalized?.sort?.length) {
13001
+ this.data.setSort(normalized.sort);
13002
+ }
13003
+ if (pageSize !== null) {
13004
+ this.data.setPage(pageIndex, pageSize);
13005
+ }
13006
+ }
12900
13007
  buildListEditorRuntimeContext(doc) {
12901
13008
  const resourcePath = doc?.config?.dataSource?.resourcePath ||
12902
13009
  this.appliedRuntimeConfig?.dataSource?.resourcePath;
@@ -12919,6 +13026,7 @@ class PraxisList {
12919
13026
  if (plan.runtime?.applyConfig) {
12920
13027
  this.data.setConfig(this.config);
12921
13028
  this.lastQuery = this.config?.dataSource?.query || {};
13029
+ this.applyRuntimeQueryContext();
12922
13030
  }
12923
13031
  if (plan.runtime?.rebindSelection) {
12924
13032
  this.setupSelectionBinding();
@@ -13489,9 +13597,9 @@ class PraxisList {
13489
13597
  if (!color || this.isThemeColor(color))
13490
13598
  return '';
13491
13599
  if (variant === 'outlined') {
13492
- return `color:${color}; border-color:${color}; background: transparent;`;
13600
+ return `--p-list-chip-color:${color}; --p-list-chip-border-color:${color}; --p-list-chip-background: transparent;`;
13493
13601
  }
13494
- return `background:${color}; color: var(--md-sys-color-on-primary);`;
13602
+ return `--p-list-chip-background:${color}; --p-list-chip-color: var(--md-sys-color-on-primary);`;
13495
13603
  }
13496
13604
  iconStyle(color) {
13497
13605
  if (!color || this.isThemeColor(color))
@@ -13767,12 +13875,12 @@ class PraxisList {
13767
13875
  return [{ key: '', value: String(value) }];
13768
13876
  }
13769
13877
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisList, deps: [], target: i0.ɵɵFactoryTarget.Component });
13770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisList, isStandalone: true, selector: "praxis-list", inputs: { config: "config", listId: "listId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", form: "form", enableCustomization: ["enableCustomization", "enableCustomization", booleanAttribute] }, outputs: { itemClick: "itemClick", actionClick: "actionClick", selectionChange: "selectionChange", exportAction: "exportAction" }, providers: [
13878
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisList, isStandalone: true, selector: "praxis-list", inputs: { config: "config", listId: "listId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", queryContext: "queryContext", form: "form", enableCustomization: ["enableCustomization", "enableCustomization", booleanAttribute] }, outputs: { itemClick: "itemClick", actionClick: "actionClick", selectionChange: "selectionChange", exportAction: "exportAction" }, providers: [
13771
13879
  GenericCrudService,
13772
13880
  ListDataService,
13773
13881
  MatPaginatorIntl,
13774
13882
  providePraxisListI18n(),
13775
- ], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"praxis-list-root\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (inlineCss) {\n <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style>\n }\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]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\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 <!-- Skeleton while loading -->\n @if ((loading$ | async) && 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 } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (config.export?.enabled) {\n <div class=\"list-export-tools\">\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 </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0) {\n <div class=\"section-header\">\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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 (simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"node?.class\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\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 [src]=\"node?.value\" [alt]=\"node?.imageAlt || imageAlt || ''\" />\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' ? 'chip-outlined' : '',\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 (slot === \"meta\" && config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\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 [attr.role]=\"clickable ? 'button' : null\"\n [attr.tabindex]=\"clickable ? '0' : null\"\n [attr.aria-label]=\"clickable ? itemAriaLabel(item) : null\"\n [attr.aria-expanded]=\"\n clickable && expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n clickable && expansionOwnedByRow()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.enter)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.space)=\"\n onRowSpaceActivate($event, clickable, item, index, sectionKey)\n \"\n >\n @for (column of rowLayoutColumns(); track rowLayoutTrackColumn($index, column)) {\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 === \"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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\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 list -->\n @if (isSelectionEnabled()) {\n <mat-selection-list\n [multiple]=\"config.selection?.mode === 'multiple'\"\n [formControl]=\"boundControl\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section)\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 [compose]=\"sh\"></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-option\n [value]=\"item\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n clickable: false,\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 <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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') ===\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) ? lead.color : 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 <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 [metric]=\"lead\"></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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 {\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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\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 (secondary(item)?.type === \"component\") {\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.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 </span>\n }\n </div>\n }\n </div>\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></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 mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </mat-list-option>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider></mat-divider>\n }\n }\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n }\n\n <!-- Read-only list -->\n <ng-template #readList>\n <mat-list>\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 @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 [attr.data-item-status]=\"item?.status || null\">\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\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)=\"onRowActivate(item, i, section.key || undefined)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-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 (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\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 @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 [metric]=\"lead\"></praxis-list-metric>\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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 === \"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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (item.segmentVariant && item.segmentLabel && item.accountType && item.since) {\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\">{{ item.accountType }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\">Desde {{ item.since }}</span>\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.class);\n as progress\n ) {\n <span\n class=\"feature-progress\"\n aria-hidden=\"true\"\n >\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></praxis-list-metric>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </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></mat-divider>\n }\n }\n }\n </mat-list>\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 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-content\">\n <div class=\"list-item-leading\">\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </span>\n }\n </div>\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 === \"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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 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 [nodes]=\"richNodes\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\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 [metric]=\"lead\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(m.color) ? m.color : undefined\"\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]=\"isThemeColor(m.color) ? m.color : undefined\"\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </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 [nodes]=\"richNodes\"></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]=\"chipStyle(tr2.color, tr2.variant)\"\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 [src]=\"tr2.value\" [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\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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 data controls -->\n @if (config.dataSource?.resourcePath) {\n @if (config.ui?.showSort || (config.ui?.showSearch && config.ui?.searchField)) {\n <div class=\"list-remote-tools\">\n @if (config.ui?.showSort) {\n <mat-form-field class=\"paginator-sort\" appearance=\"outline\">\n <mat-label>Ordenar</mat-label>\n <mat-select (selectionChange)=\"onSortChange($event.value)\">\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 @if (config.ui?.showSearch && config.ui?.searchField) {\n <mat-form-field class=\"paginator-search\" appearance=\"outline\">\n <mat-label>{{\n config.ui?.searchPlaceholder || \"Buscar\"\n }}</mat-label>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n </div>\n }\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{--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);--p-list-grad-foreground-muted: var(--md-sys-color-on-primary);--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--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-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,.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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,.praxis-list-root.lines-3 .mat-mdc-list-option{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{display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),max-content);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)}.list-item-content--row-layout[role=button]{cursor:pointer}.list-item-content--row-layout[role=button]:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{min-width:0;display:flex;align-items:center;gap:8px}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary{min-width:0}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:wrap;justify-content:flex-end}.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-height:100%}.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{min-width:0;display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:4px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap}.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,.mat-mdc-list-option{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,.mat-mdc-list-option.mdc-list-item--with-one-line,.mat-mdc-list-option.mdc-list-item--with-two-lines,.mat-mdc-list-option.mdc-list-item--with-three-lines{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item,.density-compact .mat-mdc-list-option{min-height:40px}.density-comfortable .mat-mdc-list-item,.density-comfortable .mat-mdc-list-option{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item,.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-option{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-option .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text,.mat-mdc-list-option .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,.mat-mdc-list-option{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list>mat-list-item:not(:last-child),.praxis-list-root mat-selection-list>mat-list-option:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.mat-mdc-list-item:hover .list-item-content,.mat-mdc-list-option:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content,.mat-mdc-list-option:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-option.mdc-list-item--selected .list-item-content{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.mat-mdc-list-option.cdk-keyboard-focused .list-item-content,.mat-mdc-list-option.cdk-focused .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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;white-space:nowrap}.trailing{color:var(--p-list-foreground-muted);margin-left:0;white-space:nowrap}.section-header{font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.praxis-list-root mat-list,.praxis-list-root mat-selection-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:14px 16px;background:color-mix(in srgb,var(--p-list-surface) 88%,white 12%);border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.item-expansion-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));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}.expansion-key-value-row{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-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.78rem;font-weight:600;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.9rem;color:var(--p-list-foreground)}.cards-grid,.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(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)}.item-tile:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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-visible .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{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:var(--p-list-tile-padding);display:flex;flex-direction:column;min-height:160px;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}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width)}.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)}.item-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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:10px;right:10px;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto}.leading-icon.mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);font-size:var(--p-list-chip-font-size)}.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:transparent!important;border:1px solid currentColor}.w-60{width:60%}.w-40{width:40%}.list-remote-tools{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:14px;padding:14px 4px 8px;border-top:1px solid var(--md-sys-color-outline-variant);position:relative;z-index:1;background:var(--p-list-surface-low);border-radius:calc(var(--p-list-radius) * .75)}.list-export-tools{display:flex;justify-content:flex-end;margin:0 0 12px}.list-export-tools button{border-radius:8px}.list-export-tools .mat-icon{margin-right:6px}.paginator-sort{width:180px}.paginator-search{min-width:220px}.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, #fff);background:var(--md-sys-color-surface-container, #fff)!important;background-color:var(--md-sys-color-surface-container, #fff)!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)}@media(max-width:720px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-trailing{grid-column:1/-1;padding-right:0;align-items:flex-start;text-align:start}.item-expansion{margin-left:0;margin-right:0}.list-remote-tools{align-items:stretch}.paginator-sort,.paginator-search{width:100%;min-width:0}}\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: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i3.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i3.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { 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: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5.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: i6.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: i6.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$1.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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.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: i8$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i10$1.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$1.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$1.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: i12.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", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "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"] }, { 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: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13883
+ ], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"praxis-list-root\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (inlineCss) {\n <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style>\n }\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]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\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 <!-- Skeleton while loading -->\n @if ((loading$ | async) && 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 } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (config.export?.enabled) {\n <div class=\"list-export-tools\">\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 </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0) {\n <div class=\"section-header\">\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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 (simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"node?.class\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\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 [src]=\"node?.value\" [alt]=\"node?.imageAlt || imageAlt || ''\" />\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' ? 'chip-outlined' : '',\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 (slot === \"meta\" && config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\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 [attr.role]=\"clickable ? 'button' : null\"\n [attr.tabindex]=\"clickable ? '0' : null\"\n [attr.aria-label]=\"clickable ? itemAriaLabel(item) : null\"\n [attr.aria-expanded]=\"\n clickable && expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n clickable && expansionOwnedByRow()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.enter)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.space)=\"\n onRowSpaceActivate($event, clickable, item, index, sectionKey)\n \"\n >\n @for (column of rowLayoutColumns(); track rowLayoutTrackColumn($index, column)) {\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 === \"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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\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 list -->\n @if (isSelectionEnabled()) {\n <mat-selection-list\n [multiple]=\"config.selection?.mode === 'multiple'\"\n [formControl]=\"boundControl\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section)\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 [compose]=\"sh\"></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-option\n [value]=\"item\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n clickable: false,\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 <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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') ===\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) ? lead.color : 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 <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 [metric]=\"lead\"></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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 {\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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\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 (secondary(item)?.type === \"component\") {\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.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 </span>\n }\n </div>\n }\n </div>\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></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 mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </mat-list-option>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider></mat-divider>\n }\n }\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n }\n\n <!-- Read-only list -->\n <ng-template #readList>\n <mat-list>\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 @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 [attr.data-item-status]=\"item?.status || null\">\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\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)=\"onRowActivate(item, i, section.key || undefined)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-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 (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\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 @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 [metric]=\"lead\"></praxis-list-metric>\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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 === \"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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (item.segmentVariant && item.segmentLabel && item.accountType && item.since) {\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\">{{ item.accountType }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\">Desde {{ item.since }}</span>\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.class);\n as progress\n ) {\n <span\n class=\"feature-progress\"\n aria-hidden=\"true\"\n >\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></praxis-list-metric>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </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></mat-divider>\n }\n }\n }\n </mat-list>\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 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-content\">\n <div class=\"list-item-leading\">\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (\n detail of detailSlots;\n track detail.slot\n ) {\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 === \"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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 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 [nodes]=\"richNodes\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\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 [metric]=\"lead\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(m.color) ? m.color : undefined\"\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]=\"isThemeColor(m.color) ? m.color : undefined\"\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </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 [nodes]=\"richNodes\"></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]=\"chipStyle(tr2.color, tr2.variant)\"\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 [src]=\"tr2.value\" [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\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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 data controls -->\n @if (config.dataSource?.resourcePath) {\n @if (config.ui?.showSort || (config.ui?.showSearch && config.ui?.searchField)) {\n <div class=\"list-remote-tools\">\n @if (config.ui?.showSort) {\n <mat-form-field class=\"paginator-sort\" appearance=\"outline\">\n <mat-label>Ordenar</mat-label>\n <mat-select (selectionChange)=\"onSortChange($event.value)\">\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 @if (config.ui?.showSearch && config.ui?.searchField) {\n <mat-form-field class=\"paginator-search\" appearance=\"outline\">\n <mat-label>{{\n config.ui?.searchPlaceholder || \"Buscar\"\n }}</mat-label>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n </div>\n }\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{--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-selection-end-gutter: 56px;--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-action-icon-button-size: 32px;--p-list-action-icon-size: 18px;--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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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,.praxis-list-root.lines-3 .mat-mdc-list-option{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)}.list-item-content--row-layout[role=button]{cursor:pointer}.list-item-content--row-layout[role=button]:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{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 .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{min-width:0}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:wrap;justify-content:flex-end}.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-height:100%}.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:grid;align-self:center;align-items:center;justify-content:end;justify-items:end;align-content:center;gap:4px;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}.list-item-actions .mat-mdc-icon-button{width:var(--p-list-action-icon-button-size);height:var(--p-list-action-icon-button-size);min-width:var(--p-list-action-icon-button-size);padding:calc((var(--p-list-action-icon-button-size) - var(--p-list-action-icon-size)) / 2);--mdc-icon-button-state-layer-size: var(--p-list-action-icon-button-size)}.list-item-actions .mat-mdc-icon-button mat-icon{width:var(--p-list-action-icon-size);height:var(--p-list-action-icon-size);font-size:var(--p-list-action-icon-size);line-height:var(--p-list-action-icon-size)}.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,.mat-mdc-list-option{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-option .mdc-list-item__end{align-self:center;margin-top:auto;margin-bottom:auto}.mat-mdc-list-option .list-item-content{padding-right:calc(var(--p-list-item-padding-x) + var(--p-list-selection-end-gutter))}.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,.mat-mdc-list-option.mdc-list-item--with-one-line,.mat-mdc-list-option.mdc-list-item--with-two-lines,.mat-mdc-list-option.mdc-list-item--with-three-lines{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item,.density-compact .mat-mdc-list-option{min-height:40px}.density-comfortable .mat-mdc-list-item,.density-comfortable .mat-mdc-list-option{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item,.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-option{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-option .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text,.mat-mdc-list-option .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,.mat-mdc-list-option{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list>mat-list-item:not(:last-child),.praxis-list-root mat-selection-list>mat-list-option:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.mat-mdc-list-item:hover .list-item-content,.mat-mdc-list-option:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content,.mat-mdc-list-option:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-option.mdc-list-item--selected .list-item-content{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.mat-mdc-list-option.cdk-keyboard-focused .list-item-content,.mat-mdc-list-option.cdk-focused .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-list-root mat-selection-list>.mat-mdc-list-option{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}.skin-elevated mat-selection-list>.mat-mdc-list-option,.skin-outline mat-selection-list>.mat-mdc-list-option,.skin-flat mat-selection-list>.mat-mdc-list-option,.skin-neumorphism mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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))}.praxis-list-root mat-selection-list>.mat-mdc-list-option:hover{background:var(--p-list-item-hover-surface)}.praxis-list-root mat-selection-list>.mat-mdc-list-option:active{background:var(--p-list-item-active-surface)}.praxis-list-root mat-selection-list>.mat-mdc-list-option.mdc-list-item--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.praxis-list-root mat-selection-list>.mat-mdc-list-option .list-item-content{background:transparent;border:0;box-shadow:none;border-radius:0}.praxis-list-root mat-selection-list>.mat-mdc-list-option.cdk-keyboard-focused,.praxis-list-root mat-selection-list>.mat-mdc-list-option.cdk-focused{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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:1px 9px;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{font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.praxis-list-root mat-list,.praxis-list-root mat-selection-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:14px 16px;background:color-mix(in srgb,var(--p-list-surface) 88%,white 12%);border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.item-expansion-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));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}.expansion-key-value-row{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-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.78rem;font-weight:600;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.9rem;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,max(340px,var(--p-list-tile-minW))),1fr));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(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)}.item-tile:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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-visible .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{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;min-height: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}.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)}.item-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);font-size:var(--p-list-chip-font-size)}.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:transparent!important;border:1px solid currentColor}.w-60{width:60%}.w-40{width:40%}.list-remote-tools{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:14px;padding:14px 4px 8px;border-top:1px solid var(--md-sys-color-outline-variant);position:relative;z-index:1;background:var(--p-list-surface-low);border-radius:calc(var(--p-list-radius) * .75)}.list-export-tools{display:flex;justify-content:flex-end;margin:0 0 12px}.list-export-tools button{border-radius:8px}.list-export-tools .mat-icon{margin-right:6px}.paginator-sort{width:180px}.paginator-search{min-width:220px}.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, #fff);background:var(--md-sys-color-surface-container, #fff)!important;background-color:var(--md-sys-color-surface-container, #fff)!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)}@media(max-width:720px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-trailing{grid-column:1/-1;padding-right:0;align-items:flex-start;text-align:start}.item-expansion{margin-left:0;margin-right:0}.list-remote-tools{align-items:stretch}.paginator-sort,.paginator-search{width:100%;min-width:0}}\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: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i3.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i3.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { 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: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5.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: i6.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: i6.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$1.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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.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: i8$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i10$1.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$1.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$1.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: i12.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", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "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"] }, { 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: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13776
13884
  }
13777
13885
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisList, decorators: [{
13778
13886
  type: Component,
@@ -13806,7 +13914,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13806
13914
  ListDataService,
13807
13915
  MatPaginatorIntl,
13808
13916
  providePraxisListI18n(),
13809
- ], template: "<div\n class=\"praxis-list-root\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (inlineCss) {\n <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style>\n }\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]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\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 <!-- Skeleton while loading -->\n @if ((loading$ | async) && 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 } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (config.export?.enabled) {\n <div class=\"list-export-tools\">\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 </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0) {\n <div class=\"section-header\">\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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 (simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"node?.class\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\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 [src]=\"node?.value\" [alt]=\"node?.imageAlt || imageAlt || ''\" />\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' ? 'chip-outlined' : '',\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 (slot === \"meta\" && config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\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 [attr.role]=\"clickable ? 'button' : null\"\n [attr.tabindex]=\"clickable ? '0' : null\"\n [attr.aria-label]=\"clickable ? itemAriaLabel(item) : null\"\n [attr.aria-expanded]=\"\n clickable && expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n clickable && expansionOwnedByRow()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.enter)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.space)=\"\n onRowSpaceActivate($event, clickable, item, index, sectionKey)\n \"\n >\n @for (column of rowLayoutColumns(); track rowLayoutTrackColumn($index, column)) {\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 === \"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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\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 list -->\n @if (isSelectionEnabled()) {\n <mat-selection-list\n [multiple]=\"config.selection?.mode === 'multiple'\"\n [formControl]=\"boundControl\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section)\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 [compose]=\"sh\"></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-option\n [value]=\"item\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n clickable: false,\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 <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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') ===\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) ? lead.color : 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 <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 [metric]=\"lead\"></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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 {\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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\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 (secondary(item)?.type === \"component\") {\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.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 </span>\n }\n </div>\n }\n </div>\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></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 mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </mat-list-option>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider></mat-divider>\n }\n }\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n }\n\n <!-- Read-only list -->\n <ng-template #readList>\n <mat-list>\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 @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 [attr.data-item-status]=\"item?.status || null\">\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\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)=\"onRowActivate(item, i, section.key || undefined)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-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 (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\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 @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 [metric]=\"lead\"></praxis-list-metric>\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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 === \"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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (item.segmentVariant && item.segmentLabel && item.accountType && item.since) {\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\">{{ item.accountType }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\">Desde {{ item.since }}</span>\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.class);\n as progress\n ) {\n <span\n class=\"feature-progress\"\n aria-hidden=\"true\"\n >\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></praxis-list-metric>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </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></mat-divider>\n }\n }\n }\n </mat-list>\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 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-content\">\n <div class=\"list-item-leading\">\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </span>\n }\n </div>\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 === \"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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 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 [nodes]=\"richNodes\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\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 [metric]=\"lead\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(m.color) ? m.color : undefined\"\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]=\"isThemeColor(m.color) ? m.color : undefined\"\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </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 [nodes]=\"richNodes\"></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]=\"chipStyle(tr2.color, tr2.variant)\"\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 [src]=\"tr2.value\" [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\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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 data controls -->\n @if (config.dataSource?.resourcePath) {\n @if (config.ui?.showSort || (config.ui?.showSearch && config.ui?.searchField)) {\n <div class=\"list-remote-tools\">\n @if (config.ui?.showSort) {\n <mat-form-field class=\"paginator-sort\" appearance=\"outline\">\n <mat-label>Ordenar</mat-label>\n <mat-select (selectionChange)=\"onSortChange($event.value)\">\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 @if (config.ui?.showSearch && config.ui?.searchField) {\n <mat-form-field class=\"paginator-search\" appearance=\"outline\">\n <mat-label>{{\n config.ui?.searchPlaceholder || \"Buscar\"\n }}</mat-label>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n </div>\n }\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{--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);--p-list-grad-foreground-muted: var(--md-sys-color-on-primary);--p-list-leading-width: 36px;--p-list-trailing-min-width: 140px;--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-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,.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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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,.praxis-list-root.lines-3 .mat-mdc-list-option{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{display:grid;grid-template-columns:var(--p-list-leading-width) minmax(0,1fr) minmax(var(--p-list-trailing-min-width),max-content);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)}.list-item-content--row-layout[role=button]{cursor:pointer}.list-item-content--row-layout[role=button]:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{min-width:0;display:flex;align-items:center;gap:8px}.list-row-slot--leading{justify-content:center}.list-row-slot--primary,.list-row-slot--secondary{min-width:0}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:wrap;justify-content:flex-end}.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-height:100%}.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{min-width:0;display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:4px;text-align:end;padding-right:var(--p-list-trailing-padding-right)}.list-item-content--row-layout .list-item-actions{justify-content:flex-end}.list-item-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;flex-wrap:wrap}.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,.mat-mdc-list-option{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,.mat-mdc-list-option.mdc-list-item--with-one-line,.mat-mdc-list-option.mdc-list-item--with-two-lines,.mat-mdc-list-option.mdc-list-item--with-three-lines{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item,.density-compact .mat-mdc-list-option{min-height:40px}.density-comfortable .mat-mdc-list-item,.density-comfortable .mat-mdc-list-option{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item,.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-option{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-option .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text,.mat-mdc-list-option .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,.mat-mdc-list-option{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list>mat-list-item:not(:last-child),.praxis-list-root mat-selection-list>mat-list-option:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.mat-mdc-list-item:hover .list-item-content,.mat-mdc-list-option:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content,.mat-mdc-list-option:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-option.mdc-list-item--selected .list-item-content{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.mat-mdc-list-option.cdk-keyboard-focused .list-item-content,.mat-mdc-list-option.cdk-focused .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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;white-space:nowrap}.trailing{color:var(--p-list-foreground-muted);margin-left:0;white-space:nowrap}.section-header{font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.praxis-list-root mat-list,.praxis-list-root mat-selection-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:14px 16px;background:color-mix(in srgb,var(--p-list-surface) 88%,white 12%);border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.item-expansion-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));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}.expansion-key-value-row{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-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.78rem;font-weight:600;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.9rem;color:var(--p-list-foreground)}.cards-grid,.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(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)}.item-tile:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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-visible .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{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:var(--p-list-tile-padding);display:flex;flex-direction:column;min-height:160px;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}.item-card .list-item-trailing{min-width:var(--p-list-trailing-min-width)}.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)}.item-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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:10px;right:10px;pointer-events:none}.status-overlay .mat-mdc-chip{pointer-events:auto}.leading-icon.mat-icon{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);font-size:var(--p-list-chip-font-size)}.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:transparent!important;border:1px solid currentColor}.w-60{width:60%}.w-40{width:40%}.list-remote-tools{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:14px;padding:14px 4px 8px;border-top:1px solid var(--md-sys-color-outline-variant);position:relative;z-index:1;background:var(--p-list-surface-low);border-radius:calc(var(--p-list-radius) * .75)}.list-export-tools{display:flex;justify-content:flex-end;margin:0 0 12px}.list-export-tools button{border-radius:8px}.list-export-tools .mat-icon{margin-right:6px}.paginator-sort{width:180px}.paginator-search{min-width:220px}.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, #fff);background:var(--md-sys-color-surface-container, #fff)!important;background-color:var(--md-sys-color-surface-container, #fff)!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)}@media(max-width:720px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-trailing{grid-column:1/-1;padding-right:0;align-items:flex-start;text-align:start}.item-expansion{margin-left:0;margin-right:0}.list-remote-tools{align-items:stretch}.paginator-sort,.paginator-search{width:100%;min-width:0}}\n"] }]
13917
+ ], template: "<div\n class=\"praxis-list-root\"\n [ngClass]=\"skinClasses\"\n [attr.data-skin-scope]=\"skinScopeId\"\n [attr.aria-label]=\"config.a11y?.ariaLabel || null\"\n [attr.aria-labelledby]=\"config.a11y?.ariaLabelledBy || null\"\n>\n @if (inlineCss) {\n <style [attr.nonce]=\"cspNonce || null\" [textContent]=\"inlineCss\"></style>\n }\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]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\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 <!-- Skeleton while loading -->\n @if ((loading$ | async) && 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 } @else {\n <ng-container *ngTemplateOutlet=\"notLoading\"></ng-container>\n }\n\n <ng-template #notLoading>\n @if (config.export?.enabled) {\n <div class=\"list-export-tools\">\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 </div>\n }\n\n <!-- Empty state -->\n @if (items$ | async; as all) {\n @if (all.length === 0) {\n <div class=\"section-header\">\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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]=\"isThemeColor(empty.color) ? empty.color : undefined\"\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 (simpleRichContentNodes(node, { slot: slot, imageAlt: imageAlt }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (node?.type) {\n @case (\"icon\") {\n <mat-icon\n [praxisIcon]=\"node?.value\"\n [ngClass]=\"node?.class\"\n [color]=\"isThemeColor(node?.color) ? node?.color : undefined\"\n [style.cssText]=\"\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 [src]=\"node?.value\" [alt]=\"node?.imageAlt || imageAlt || ''\" />\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' ? 'chip-outlined' : '',\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 (slot === \"meta\" && config.templating?.metaPrefixIcon; as mpi) {\n <mat-icon [praxisIcon]=\"mpi\"></mat-icon>\n }\n {{ node?.value }}\n </span>\n }\n }\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 [attr.role]=\"clickable ? 'button' : null\"\n [attr.tabindex]=\"clickable ? '0' : null\"\n [attr.aria-label]=\"clickable ? itemAriaLabel(item) : null\"\n [attr.aria-expanded]=\"\n clickable && expansionOwnedByRow() ? isExpanded(item, index) : null\n \"\n [attr.aria-controls]=\"\n clickable && expansionOwnedByRow()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.enter)=\"clickable ? onRowActivate(item, index, sectionKey) : null\"\n (keydown.space)=\"\n onRowSpaceActivate($event, clickable, item, index, sectionKey)\n \"\n >\n @for (column of rowLayoutColumns(); track rowLayoutTrackColumn($index, column)) {\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 === \"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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 >\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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, 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 >\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) ? action.color : undefined\n \"\n [style.cssText]=\"buttonStyle(action.color, 'raised')\"\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 >\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 || action.buttonVariant === \"flat\") {\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, 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 >\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 mat-icon-button\n type=\"button\"\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()\n ? expandRegionId(item, index)\n : null\n \"\n (click)=\"onExpandToggle($event, item, index)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, index) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\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 list -->\n @if (isSelectionEnabled()) {\n <mat-selection-list\n [multiple]=\"config.selection?.mode === 'multiple'\"\n [formControl]=\"boundControl\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (\n section of sections$ | async;\n track trackBySection($index, section)\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 [compose]=\"sh\"></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-option\n [value]=\"item\"\n [attr.aria-label]=\"itemAriaLabel(item)\"\n >\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\n clickable: false,\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 <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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') ===\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) ? lead.color : 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 <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 [metric]=\"lead\"></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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 {\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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\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 (secondary(item)?.type === \"component\") {\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.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 </span>\n }\n </div>\n }\n </div>\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></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 mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </mat-list-option>\n @if (\n (config.layout?.dividers === \"all\" ||\n config.layout?.dividers === \"between\") &&\n i < section.items.length - 1\n ) {\n <mat-divider></mat-divider>\n }\n }\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"readList\"></ng-container>\n }\n\n <!-- Read-only list -->\n <ng-template #readList>\n <mat-list>\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: config.templating?.sectionHeader?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\n [style.cssText]=\"\n (sh.style ? sh.style + ';' : '') + 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]=\"isThemeColor(sh.color) ? sh.color : undefined\"\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 @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 [attr.data-item-status]=\"item?.status || null\">\n @if (hasRowLayoutGrid()) {\n <ng-container\n *ngTemplateOutlet=\"\n listRowLayout;\n context: {\n $implicit: item,\n index: i,\n sectionKey: section.key || undefined,\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)=\"onRowActivate(item, i, section.key || undefined)\"\n >\n <div class=\"list-item-leading\">\n @if (leading(item); as lead) {\n @if (\n simpleRichContentNodes(lead, {\n imageAlt: config.templating?.leading?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\n @case (\"icon\") {\n <mat-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 (lead.style ? lead.style + ';' : '') +\n iconStyle(lead.color)\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 @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 [metric]=\"lead\"></praxis-list-metric>\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 (simpleRichContentNodes(primary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 === \"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 (simpleRichContentNodes(secondary(item)); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (item.segmentVariant && item.segmentLabel && item.accountType && item.since) {\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\">{{ item.accountType }}</span>\n <span class=\"exec-subseparator\">\u00B7</span>\n <span class=\"exec-subcopy\">Desde {{ item.since }}</span>\n </span>\n } @else if (secondary(item)?.type === \"html\") {\n <span [innerHTML]=\"secondary(item)?.value\"></span>\n } @else if (secondary(item)?.type === \"metric\") {\n <praxis-list-metric\n [metric]=\"secondary(item)\"\n ></praxis-list-metric>\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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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]=\"\n featureSemanticClass(item, f.expr, f.class)\n \"\n >\n @if (featureRichContentNodes(item, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span\n [ngClass]=\"f.class\"\n [style.cssText]=\"f.style\"\n >\n @for (\n line of featureLabelLines(item, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(item, f.expr, f.class);\n as progress\n ) {\n <span\n class=\"feature-progress\"\n aria-hidden=\"true\"\n >\n <span\n class=\"feature-progress__value\"\n [style.width.%]=\"progress\"\n ></span>\n </span>\n }\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 === \"currency\")\n )\n ) {\n <div\n class=\"meta\"\n [ngClass]=\"m.class\"\n [style.cssText]=\"m.style\"\n >\n @if (simpleRichContentNodes(m, { slot: 'meta' }); as richNodes) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @default {\n <span>\n @if (\n config.templating?.metaPrefixIcon;\n as mpi2\n ) {\n <mat-icon [praxisIcon]=\"mpi2\"></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: config.templating?.trailing?.imageAlt || \"\",\n });\n as richNodes\n ) {\n <praxis-rich-content [nodes]=\"richNodes\"></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 @if (item.alertsData !== undefined && item.ownerName) {\n <!-- Component-based rendering for executive trailing -->\n <span class=\"exec-trailing-shell\">\n <praxis-executive-alerts [alerts]=\"item.alertsData\"></praxis-executive-alerts>\n <praxis-executive-owner [name]=\"item.ownerName\"></praxis-executive-owner>\n </span>\n } @else {\n <span [innerHTML]=\"tr.value\"></span>\n }\n }\n @case (\"metric\") {\n <praxis-list-metric [metric]=\"tr\"></praxis-list-metric>\n }\n @default {\n <span>{{ tr.value }}</span>\n }\n }\n }\n </div>\n }\n @if (showExpandIcon(\"trailing\")) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"expand-toggle\"\n [attr.aria-label]=\"expandToggleAriaLabel(item, i)\"\n [attr.aria-expanded]=\"\n expansionOwnedByIcon() ? isExpanded(item, i) : null\n \"\n [attr.aria-controls]=\"\n expansionOwnedByIcon()\n ? expandRegionId(item, i)\n : null\n \"\n (click)=\"onExpandToggle($event, item, i)\"\n >\n <mat-icon\n [praxisIcon]=\"\n isExpanded(item, i) ? 'expand_less' : 'expand_more'\n \"\n ></mat-icon>\n </button>\n }\n @if ((visibleActions(item, \"trailing\") || []).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 mat-icon-button\n [color]=\"\n isThemeColor(action.color)\n ? action.color\n : undefined\n \"\n (click)=\"\n onActionClick($event, action.id, item, i)\n \"\n [attr.aria-label]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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]=\"action.label || action.id\"\n [disabled]=\"isActionLoading(action.id, item, i)\"\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 </div>\n }\n </div>\n </div>\n }\n @if (isExpandable() && isExpanded(item, i)) {\n <div\n class=\"item-expansion\"\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 @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 </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></mat-divider>\n }\n }\n }\n </mat-list>\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 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-content\">\n <div class=\"list-item-leading\">\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (lead.type) {\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 (\"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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 === \"currency\")) ||\n (layoutLines > 2 &&\n (m?.type === \"text\" ||\n m?.type === \"date\" ||\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </span>\n }\n </div>\n }\n @if (cardDetailSlots(it); as detailSlots) {\n @if (detailSlots.length) {\n <div class=\"card-detail-strip\">\n @for (\n detail of detailSlots;\n track detail.slot\n ) {\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 === \"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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 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 [nodes]=\"richNodes\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">\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 [metric]=\"lead\"></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 [ngClass]=\"lead.class\" [style.cssText]=\"lead.style\">{{\n lead.value\n }}</span>\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @if (tr?.type === \"chip\") {\n <mat-chip\n [color]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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]=\"isThemeColor(tr.color) ? tr.color : undefined\"\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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else if (primary(it)?.type === \"metric\") {\n <praxis-list-metric [metric]=\"primary(it)\"></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 [nodes]=\"richNodes\"></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 [nodes]=\"richNodes\"></praxis-rich-content>\n } @else {\n @switch (m.type) {\n @case (\"chip\") {\n <mat-chip\n [color]=\"isThemeColor(m.color) ? m.color : undefined\"\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]=\"isThemeColor(m.color) ? m.color : undefined\"\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 @if (featureRichContentNodes(it, f); as featureNodes) {\n <praxis-rich-content [nodes]=\"featureNodes\"></praxis-rich-content>\n } @else {\n @if (f.icon && featuresMode() !== \"labels-only\") {\n <mat-icon [praxisIcon]=\"f.icon\"></mat-icon>\n }\n @if (featuresMode() !== \"icons-only\") {\n <span [ngClass]=\"f.class\" [style.cssText]=\"f.style\">\n @for (\n line of featureLabelLines(it, f.expr);\n track $index\n ) {\n <span class=\"feature-line\">{{ line }}</span>\n }\n </span>\n }\n }\n @if (\n featureProgressPercent(it, f.expr, f.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 </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 [nodes]=\"richNodes\"></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]=\"chipStyle(tr2.color, tr2.variant)\"\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 [src]=\"tr2.value\" [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\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 mat-icon-button\n [color]=\"\n isThemeColor(action.color) ? action.color : undefined\n \"\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 <mat-icon\n [praxisIcon]=\"action.icon\"\n [style.cssText]=\"iconStyle(action.color)\"\n ></mat-icon>\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 data controls -->\n @if (config.dataSource?.resourcePath) {\n @if (config.ui?.showSort || (config.ui?.showSearch && config.ui?.searchField)) {\n <div class=\"list-remote-tools\">\n @if (config.ui?.showSort) {\n <mat-form-field class=\"paginator-sort\" appearance=\"outline\">\n <mat-label>Ordenar</mat-label>\n <mat-select (selectionChange)=\"onSortChange($event.value)\">\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 @if (config.ui?.showSearch && config.ui?.searchField) {\n <mat-form-field class=\"paginator-search\" appearance=\"outline\">\n <mat-label>{{\n config.ui?.searchPlaceholder || \"Buscar\"\n }}</mat-label>\n <input\n matInput\n type=\"search\"\n (input)=\"onSearchInput($any($event.target).value)\"\n />\n </mat-form-field>\n }\n </div>\n }\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{--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-selection-end-gutter: 56px;--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-action-icon-button-size: 32px;--p-list-action-icon-size: 18px;--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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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:var(--md-sys-color-surface-container-low);border-radius:var(--p-list-radius);border:1px solid var(--md-sys-color-outline-variant);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,.praxis-list-root.lines-3 .mat-mdc-list-option{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)}.list-item-content--row-layout[role=button]{cursor:pointer}.list-item-content--row-layout[role=button]:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.list-row-slot{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 .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{min-width:0}.list-row-slot--meta{color:var(--p-list-foreground);font-variant-numeric:tabular-nums}.list-row-slot--trailing{flex-wrap:wrap;justify-content:flex-end}.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-height:100%}.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:grid;align-self:center;align-items:center;justify-content:end;justify-items:end;align-content:center;gap:4px;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}.list-item-actions .mat-mdc-icon-button{width:var(--p-list-action-icon-button-size);height:var(--p-list-action-icon-button-size);min-width:var(--p-list-action-icon-button-size);padding:calc((var(--p-list-action-icon-button-size) - var(--p-list-action-icon-size)) / 2);--mdc-icon-button-state-layer-size: var(--p-list-action-icon-button-size)}.list-item-actions .mat-mdc-icon-button mat-icon{width:var(--p-list-action-icon-size);height:var(--p-list-action-icon-size);font-size:var(--p-list-action-icon-size);line-height:var(--p-list-action-icon-size)}.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,.mat-mdc-list-option{height:auto;align-items:stretch;overflow:visible}.mat-mdc-list-option .mdc-list-item__end{align-self:center;margin-top:auto;margin-bottom:auto}.mat-mdc-list-option .list-item-content{padding-right:calc(var(--p-list-item-padding-x) + var(--p-list-selection-end-gutter))}.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,.mat-mdc-list-option.mdc-list-item--with-one-line,.mat-mdc-list-option.mdc-list-item--with-two-lines,.mat-mdc-list-option.mdc-list-item--with-three-lines{height:auto!important}.mdc-list-item{overflow:visible}.density-compact .mat-mdc-list-item,.density-compact .mat-mdc-list-option{min-height:40px}.density-comfortable .mat-mdc-list-item,.density-comfortable .mat-mdc-list-option{min-height:46px}.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-item,.praxis-list-root:not(.density-compact):not(.density-comfortable) .mat-mdc-list-option{min-height:48px}.mat-mdc-list-item .mdc-list-item__content,.mat-mdc-list-option .mdc-list-item__content,.mat-mdc-list-item .mdc-list-item__primary-text,.mat-mdc-list-option .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,.mat-mdc-list-option{padding:0!important;box-sizing:border-box}.praxis-list-root mat-list>mat-list-item:not(:last-child),.praxis-list-root mat-selection-list>mat-list-option:not(:last-child){margin-bottom:var(--p-list-item-stack-gap)}.mat-mdc-list-item:hover .list-item-content,.mat-mdc-list-option:hover .list-item-content{background:var(--p-list-item-hover-surface)}.mat-mdc-list-item:active .list-item-content,.mat-mdc-list-option:active .list-item-content{background:var(--p-list-item-active-surface)}.mat-mdc-list-option.mdc-list-item--selected .list-item-content{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.mat-mdc-list-option.cdk-keyboard-focused .list-item-content,.mat-mdc-list-option.cdk-focused .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.mat-mdc-list-item:focus-visible .list-item-content{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-list-root mat-selection-list>.mat-mdc-list-option{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}.skin-elevated mat-selection-list>.mat-mdc-list-option,.skin-outline mat-selection-list>.mat-mdc-list-option,.skin-flat mat-selection-list>.mat-mdc-list-option,.skin-neumorphism mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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 mat-selection-list>.mat-mdc-list-option{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))}.praxis-list-root mat-selection-list>.mat-mdc-list-option:hover{background:var(--p-list-item-hover-surface)}.praxis-list-root mat-selection-list>.mat-mdc-list-option:active{background:var(--p-list-item-active-surface)}.praxis-list-root mat-selection-list>.mat-mdc-list-option.mdc-list-item--selected{background:var(--p-list-item-selected-surface);border-color:var(--md-sys-color-outline-variant)}.praxis-list-root mat-selection-list>.mat-mdc-list-option .list-item-content{background:transparent;border:0;box-shadow:none;border-radius:0}.praxis-list-root mat-selection-list>.mat-mdc-list-option.cdk-keyboard-focused,.praxis-list-root mat-selection-list>.mat-mdc-list-option.cdk-focused{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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:1px 9px;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{font-size:.85rem;color:var(--p-list-foreground-muted);padding:8px 12px}.praxis-list-root mat-list,.praxis-list-root mat-selection-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:14px 16px;background:color-mix(in srgb,var(--p-list-surface) 88%,white 12%);border:1px solid var(--md-sys-color-outline-variant);border-radius:calc(var(--p-list-radius) * .75)}.item-expansion-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));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}.expansion-key-value-row{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-key-value-row dt,.expansion-key-value-row dd{margin:0}.expansion-key-value-row dt{font-size:.78rem;font-weight:600;color:var(--p-list-foreground-muted)}.expansion-key-value-row dd{font-size:.9rem;color:var(--p-list-foreground)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,max(340px,var(--p-list-tile-minW))),1fr));gap:max(var(--p-list-tile-gap),16px)}.tiles-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(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)}.item-tile:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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-visible .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{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;min-height: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}.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)}.item-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.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{width:36px;height:36px;line-height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.mat-mdc-chip{--mdc-chip-container-height: var(--p-list-chip-height);font-size:var(--p-list-chip-font-size)}.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:transparent!important;border:1px solid currentColor}.w-60{width:60%}.w-40{width:40%}.list-remote-tools{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:14px;padding:14px 4px 8px;border-top:1px solid var(--md-sys-color-outline-variant);position:relative;z-index:1;background:var(--p-list-surface-low);border-radius:calc(var(--p-list-radius) * .75)}.list-export-tools{display:flex;justify-content:flex-end;margin:0 0 12px}.list-export-tools button{border-radius:8px}.list-export-tools .mat-icon{margin-right:6px}.paginator-sort{width:180px}.paginator-search{min-width:220px}.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, #fff);background:var(--md-sys-color-surface-container, #fff)!important;background-color:var(--md-sys-color-surface-container, #fff)!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)}@media(max-width:720px){.list-item-content{grid-template-columns:var(--p-list-leading-width) minmax(0,1fr)}.list-item-trailing{grid-column:1/-1;padding-right:0;align-items:flex-start;text-align:start}.item-expansion{margin-left:0;margin-right:0}.list-remote-tools{align-items:stretch}.paginator-sort,.paginator-search{width:100%;min-width:0}}\n"] }]
13810
13918
  }], propDecorators: { config: [{
13811
13919
  type: Input
13812
13920
  }], listId: [{
@@ -13816,6 +13924,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13816
13924
  type: Input
13817
13925
  }], configPersistenceStrategy: [{
13818
13926
  type: Input
13927
+ }], queryContext: [{
13928
+ type: Input
13819
13929
  }], form: [{
13820
13930
  type: Input
13821
13931
  }], enableCustomization: [{
@@ -14078,6 +14188,7 @@ const PRAXIS_LIST_COMPONENT_METADATA = {
14078
14188
  { name: 'listId', type: 'string', description: 'Identificador da lista (obrigatório para persistência)' },
14079
14189
  { name: 'componentInstanceId', type: 'string', description: 'Identificador opcional para múltiplas instâncias na mesma rota' },
14080
14190
  { name: 'configPersistenceStrategy', type: "'local-first' | 'input-first'", default: 'local-first', description: 'Define se a configuração local persistida ou a configuração recebida por input tem precedência na hidratação.' },
14191
+ { name: 'queryContext', type: 'PraxisDataQueryContext | null', description: 'Contexto runtime declarativo para filtros, ordenação e paginação sem persistir na configuração autorada.' },
14081
14192
  { name: 'form', type: 'FormGroup', description: 'FormGroup opcional quando integrado a formulários' },
14082
14193
  { name: 'enableCustomization', type: 'boolean', description: 'Input canônico para habilitar customização runtime, editor e AI assistant' },
14083
14194
  ],
@@ -14982,6 +15093,10 @@ class PraxisListDocPageComponent {
14982
15093
  selection: { mode: 'none' },
14983
15094
  dataSource: { data: this.skinPreviewItems },
14984
15095
  skin: this.buildSkinConfig(type),
15096
+ templating: {
15097
+ ...this.buildTemplatingConfig(true),
15098
+ statusPosition: 'top-right',
15099
+ },
14985
15100
  },
14986
15101
  })), ...(ngDevMode ? [{ debugName: "skinPreviewConfigs" }] : []));
14987
15102
  configPreview = computed(() => {
@@ -15173,7 +15288,7 @@ export class ListDocHostComponent {}`;
15173
15288
  },
15174
15289
  trailing: {
15175
15290
  type: 'chip',
15176
- expr: '${item.status}',
15291
+ expr: '${item.status}|map:available=Disponivel,last_rooms=Ultimas unidades,sold_out=Lotado',
15177
15292
  variant: 'filled',
15178
15293
  },
15179
15294
  metaPlacement: 'line',
@@ -15341,7 +15456,7 @@ export class ListDocHostComponent {}`;
15341
15456
  },
15342
15457
  trailing: {
15343
15458
  type: 'chip',
15344
- expr: '${item.status}',
15459
+ expr: '${item.status}|map:done=Concluido,risk=Risco,watch=Monitorar,paused=Pausado',
15345
15460
  },
15346
15461
  metaPlacement: this.lines() >= 3 ? 'line' : 'side',
15347
15462
  metaPrefixIcon: 'payments',
@@ -15406,7 +15521,7 @@ export class ListDocHostComponent {}`;
15406
15521
  useFactory: () => new LocalStorageAsyncAdapter(new LocalStorageConfigService()),
15407
15522
  },
15408
15523
  { provide: SETTINGS_PANEL_DATA, useValue: {} },
15409
- ], 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;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.skin-preview{padding:12px}.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: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PraxisList, selector: "praxis-list", inputs: ["config", "listId", "componentInstanceId", "configPersistenceStrategy", "form", "enableCustomization"], outputs: ["itemClick", "actionClick", "selectionChange", "exportAction"] }, { kind: "component", type: PraxisListSkinPreviewComponent, selector: "praxis-list-skin-preview", inputs: ["config", "items", "theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
15524
+ ], 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: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PraxisList, selector: "praxis-list", inputs: ["config", "listId", "componentInstanceId", "configPersistenceStrategy", "queryContext", "form", "enableCustomization"], outputs: ["itemClick", "actionClick", "selectionChange", "exportAction"] }, { kind: "component", type: PraxisListSkinPreviewComponent, selector: "praxis-list-skin-preview", inputs: ["config", "items", "theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
15410
15525
  }
15411
15526
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisListDocPageComponent, decorators: [{
15412
15527
  type: Component,
@@ -15422,7 +15537,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15422
15537
  useFactory: () => new LocalStorageAsyncAdapter(new LocalStorageConfigService()),
15423
15538
  },
15424
15539
  { provide: SETTINGS_PANEL_DATA, useValue: {} },
15425
- ], 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;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.skin-preview{padding:12px}.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"] }]
15540
+ ], 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"] }]
15426
15541
  }] });
15427
15542
 
15428
15543
  /*