@testgorilla/tgo-ui 11.0.1 → 11.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/fesm2022/testgorilla-tgo-ui-components-accordion.mjs +7 -7
  2. package/fesm2022/testgorilla-tgo-ui-components-ai-audio-circle.mjs +7 -7
  3. package/fesm2022/testgorilla-tgo-ui-components-ai-caveat.mjs +7 -7
  4. package/fesm2022/testgorilla-tgo-ui-components-ai-feedback.mjs +7 -7
  5. package/fesm2022/testgorilla-tgo-ui-components-alert-banner.mjs +7 -7
  6. package/fesm2022/testgorilla-tgo-ui-components-audio-waveform.mjs +10 -10
  7. package/fesm2022/testgorilla-tgo-ui-components-autocomplete-v2.mjs +15 -15
  8. package/fesm2022/testgorilla-tgo-ui-components-autocomplete.mjs +19 -19
  9. package/fesm2022/testgorilla-tgo-ui-components-avatar.mjs +10 -10
  10. package/fesm2022/testgorilla-tgo-ui-components-badge.mjs +7 -7
  11. package/fesm2022/testgorilla-tgo-ui-components-breadcrumb.mjs +7 -7
  12. package/fesm2022/testgorilla-tgo-ui-components-button.mjs +7 -7
  13. package/fesm2022/testgorilla-tgo-ui-components-card.mjs +7 -7
  14. package/fesm2022/testgorilla-tgo-ui-components-checkbox.mjs +10 -10
  15. package/fesm2022/testgorilla-tgo-ui-components-checklist.mjs +3 -3
  16. package/fesm2022/testgorilla-tgo-ui-components-core.mjs +42 -42
  17. package/fesm2022/testgorilla-tgo-ui-components-datepicker.mjs +19 -19
  18. package/fesm2022/testgorilla-tgo-ui-components-dialog.mjs +24 -24
  19. package/fesm2022/testgorilla-tgo-ui-components-divider.mjs +7 -7
  20. package/fesm2022/testgorilla-tgo-ui-components-donut-chart.mjs +7 -7
  21. package/fesm2022/testgorilla-tgo-ui-components-dropdown.mjs +7 -7
  22. package/fesm2022/testgorilla-tgo-ui-components-elevation-shadow.mjs +7 -7
  23. package/fesm2022/testgorilla-tgo-ui-components-empty-state.mjs +7 -7
  24. package/fesm2022/testgorilla-tgo-ui-components-field.mjs +7 -7
  25. package/fesm2022/testgorilla-tgo-ui-components-file-upload.mjs +10 -10
  26. package/fesm2022/testgorilla-tgo-ui-components-filter-button.mjs +7 -7
  27. package/fesm2022/testgorilla-tgo-ui-components-gaussian-chart.mjs +7 -7
  28. package/fesm2022/testgorilla-tgo-ui-components-icon-label.mjs +7 -7
  29. package/fesm2022/testgorilla-tgo-ui-components-icon.mjs +10 -10
  30. package/fesm2022/testgorilla-tgo-ui-components-infinite-scroll-table.mjs +109 -21
  31. package/fesm2022/testgorilla-tgo-ui-components-infinite-scroll-table.mjs.map +1 -1
  32. package/fesm2022/testgorilla-tgo-ui-components-inline-field.mjs +7 -7
  33. package/fesm2022/testgorilla-tgo-ui-components-logo.mjs +7 -7
  34. package/fesm2022/testgorilla-tgo-ui-components-media-card.mjs +3 -3
  35. package/fesm2022/testgorilla-tgo-ui-components-media-dialog.mjs +3 -3
  36. package/fesm2022/testgorilla-tgo-ui-components-multi-input.mjs +7 -7
  37. package/fesm2022/testgorilla-tgo-ui-components-navbar.mjs +10 -10
  38. package/fesm2022/testgorilla-tgo-ui-components-overflow-menu.mjs +7 -7
  39. package/fesm2022/testgorilla-tgo-ui-components-page-header.mjs +7 -7
  40. package/fesm2022/testgorilla-tgo-ui-components-paginator.mjs +7 -7
  41. package/fesm2022/testgorilla-tgo-ui-components-password-criteria.mjs +7 -7
  42. package/fesm2022/testgorilla-tgo-ui-components-password-strength.mjs +7 -7
  43. package/fesm2022/testgorilla-tgo-ui-components-phone-input.mjs +10 -10
  44. package/fesm2022/testgorilla-tgo-ui-components-popover.mjs +6 -6
  45. package/fesm2022/testgorilla-tgo-ui-components-progress-bar.mjs +7 -7
  46. package/fesm2022/testgorilla-tgo-ui-components-prompt.mjs +7 -7
  47. package/fesm2022/testgorilla-tgo-ui-components-radial-progress.mjs +7 -7
  48. package/fesm2022/testgorilla-tgo-ui-components-radio-button.mjs +7 -7
  49. package/fesm2022/testgorilla-tgo-ui-components-rating.mjs +10 -10
  50. package/fesm2022/testgorilla-tgo-ui-components-scale-table.mjs +3 -3
  51. package/fesm2022/testgorilla-tgo-ui-components-scale.mjs +7 -7
  52. package/fesm2022/testgorilla-tgo-ui-components-segmented-bar.mjs +7 -7
  53. package/fesm2022/testgorilla-tgo-ui-components-segmented-button.mjs +7 -7
  54. package/fesm2022/testgorilla-tgo-ui-components-segmented-toggle.mjs +3 -3
  55. package/fesm2022/testgorilla-tgo-ui-components-selectable-card.mjs +7 -7
  56. package/fesm2022/testgorilla-tgo-ui-components-side-navigation.mjs +7 -7
  57. package/fesm2022/testgorilla-tgo-ui-components-side-panel.mjs +6 -6
  58. package/fesm2022/testgorilla-tgo-ui-components-side-sheet.mjs +10 -10
  59. package/fesm2022/testgorilla-tgo-ui-components-skeleton.mjs +3 -3
  60. package/fesm2022/testgorilla-tgo-ui-components-slider.mjs +7 -7
  61. package/fesm2022/testgorilla-tgo-ui-components-snackbar.mjs +10 -10
  62. package/fesm2022/testgorilla-tgo-ui-components-spider-chart.mjs +7 -7
  63. package/fesm2022/testgorilla-tgo-ui-components-spinner.mjs +7 -7
  64. package/fesm2022/testgorilla-tgo-ui-components-stepper.mjs +17 -17
  65. package/fesm2022/testgorilla-tgo-ui-components-table.mjs +10 -10
  66. package/fesm2022/testgorilla-tgo-ui-components-tabs.mjs +10 -10
  67. package/fesm2022/testgorilla-tgo-ui-components-tag.mjs +7 -7
  68. package/fesm2022/testgorilla-tgo-ui-components-toggle.mjs +7 -7
  69. package/fesm2022/testgorilla-tgo-ui-components-tooltip.mjs +10 -10
  70. package/fesm2022/testgorilla-tgo-ui-components-universal-skills.mjs +17 -17
  71. package/fesm2022/testgorilla-tgo-ui-components-validation-error.mjs +7 -7
  72. package/fesm2022/testgorilla-tgo-ui-components-write-with-ai.mjs +10 -10
  73. package/fesm2022/testgorilla-tgo-ui.mjs +7 -7
  74. package/mcp/catalog.json +1 -1
  75. package/package.json +1 -1
  76. package/types/testgorilla-tgo-ui-components-infinite-scroll-table.d.ts +35 -5
@@ -240,10 +240,10 @@ class GaussianChartComponent {
240
240
  return 'PERCENTILE_LABEL_TYPES.WELL_ABOVE_AVERAGE';
241
241
  }
242
242
  }
243
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
244
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: GaussianChartComponent, isStandalone: true, selector: "ui-gaussian-chart", inputs: { score: "score", bestCandidateScore: "bestCandidateScore", applicationTheme: "applicationTheme", legendPosition: "legendPosition" }, ngImport: i0, template: "@if (score) {\n <div\n class=\"chart-section\"\n [attr.aria-label]=\"\n translationContext + 'ARIA_LABEL'\n | uiTranslate\n : {\n score: score,\n activeBucket: getScoreTranslationKey(score) | uiTranslate | async,\n bestCandidateScore: bestCandidateScore,\n activeBucketBestScore: getScoreTranslationKey(bestCandidateScore) | uiTranslate | async,\n }\n | async\n \"\n tabindex=\"0\"\n >\n <!-- Legend positioned at top -->\n @if (legendPosition === 'top-start' || legendPosition === 'top-end') {\n <ng-container [ngTemplateOutlet]=\"legendTemplate\"></ng-container>\n }\n <div class=\"chart-range-wrapper\">\n <div class=\"normal-chart-container\">\n <div class=\"normal-chart\">\n <canvas baseChart [data]=\"gaussianChartData\" [options]=\"gaussianChartOptions\" type=\"line\" class=\"chart\">\n </canvas>\n <div\n class=\"overlay-icon\"\n [style.bottom]=\"[overlayYValue, 3, 'subtract'] | memoizeFunc: getCalcPosition\"\n [style.left]=\"[overlayXValue, 20, 'subtract'] | memoizeFunc: getCalcPosition\"\n >\n <div class=\"drop-icon\">\n <ui-icon name=\"Pin-marker\" size=\"40\"></ui-icon>\n <span class=\"curve-score\">{{ score }}</span>\n </div>\n </div>\n <div\n class=\"best-score\"\n [style.height]=\"\n [100 - overlayYBestScoreValue, normalContainerPadding, 'add'] | memoizeFunc: getCalcPosition\n \"\n [style.bottom]=\"overlayYBestScoreValue + '%'\"\n [style.left]=\"overlayXBestScoreValue + '%'\"\n >\n <div\n class=\"best-score-content\"\n [style.left]=\"bestCandidateScore | memoizeFunc: getBestScoreContentPosition : this\"\n >\n <ui-icon name=\"Trophy\"></ui-icon>\n {{ bestCandidateScore }}\n </div>\n </div>\n </div>\n <div class=\"overlay\">\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.LOWEST\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.LOWEST\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWEST_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWEST' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.LOWER\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.LOWER\"\n [matTooltip]=\"(translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWER_TOOLTIP' | uiTranslate | async) || ''\"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWER' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.AVERAGE\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.AVERAGE\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.AVERAGE_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.AVERAGE' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.HIGHER\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.HIGHER\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHER_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHER' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.HIGHEST\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.HIGHEST\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHEST_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHEST' | uiTranslate | async }}\n </div>\n </div>\n </div>\n </div>\n <div class=\"range\">\n <div>1</div>\n <div>20</div>\n <div>40</div>\n <div>60</div>\n <div>80</div>\n <div>99</div>\n </div>\n </div>\n <!-- Legend positioned at bottom -->\n @if (legendPosition === 'bottom-start' || legendPosition === 'bottom-end') {\n <ng-container [ngTemplateOutlet]=\"legendTemplate\"></ng-container>\n }\n </div>\n}\n\n<!-- Reusable legend template -->\n<ng-template #legendTemplate>\n <div class=\"legend-container\" [ngClass]=\"'legend-' + legendPosition\">\n <div class=\"legend\">\n <ui-icon name=\"Dot\" color=\"gray\"></ui-icon>\n {{ translationContext + 'CANDIDATE_SCORE' | uiTranslate | async }}\n </div>\n <div class=\"legend\">\n <ui-icon name=\"Trophy\" color=\"gray\"></ui-icon>\n {{ translationContext + 'HIGHEST_SCORE' | uiTranslate | async }}\n </div>\n </div>\n</ng-template>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}.chart-section{display:flex;flex-direction:column;gap:16px;width:100%}.chart-section .chart-range-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.chart-section .chart-range-wrapper .normal-chart-container{position:relative;padding-bottom:32px;padding-top:50px;border:1px solid #d3d3d3;border-radius:10px;width:100%;height:230px}.chart-section .chart-range-wrapper .normal-chart-container .normal-chart{position:relative;z-index:1;width:100%;height:100%}.chart-section .chart-range-wrapper .normal-chart-container .overlay{position:absolute;top:0;left:0;height:100%;width:100%;display:flex}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column{flex:1;font-size:12px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column .column-item{cursor:pointer}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column:not(:last-child){border-right:1px solid #d3d3d3}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active{background-color:#fff5ed;border-bottom:3px solid #242424}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child,.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child{border:none;position:relative}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child{border-right:1px solid #d3d3d3}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child:before,.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child:after{content:\"\";position:absolute;bottom:0;width:calc(100% - 4px);height:2.5px;background-color:#000}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child{border-top-left-radius:8px;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child:before{right:0;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child{border-top-right-radius:8px;border-bottom-right-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child:after{left:0;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;padding-bottom:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon{position:absolute;z-index:1;display:flex;flex-direction:column;align-items:center}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon .drop-icon{position:relative}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon .drop-icon .curve-score{font-size:14px;font-weight:700;position:absolute;width:100%;text-align:center;top:0;left:.5px;padding:4px 4px 9px}.chart-section .chart-range-wrapper .normal-chart-container .best-score{position:absolute;border-left:1px #242424 dashed}.chart-section .chart-range-wrapper .normal-chart-container .best-score .best-score-content{position:absolute;display:flex;gap:3px;align-items:center}.chart-section .chart-range-wrapper .range{display:flex;justify-content:space-between;color:#919191}.chart-section .chart-range-wrapper .range div{width:35px;text-align:center}.chart-section .chart-range-wrapper .range div:nth-child(2){text-align:left}.chart-section .chart-range-wrapper .range div:nth-last-child(2){text-align:right}.chart-section .legend-container{display:flex;gap:16px}.chart-section .legend-container.legend-top-start,.chart-section .legend-container.legend-bottom-start{justify-content:flex-start}.chart-section .legend-container.legend-top-end,.chart-section .legend-container.legend-bottom-end{justify-content:flex-end}.chart-section .legend-container .legend{display:flex;gap:8px;align-items:center;color:#666}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: BaseChartDirective, selector: "canvas[baseChart]", inputs: ["type", "legend", "data", "options", "plugins", "labels", "datasets"], outputs: ["chartClick", "chartHover"], exportAs: ["base-chart"] }, { kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i1.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: UiTranslatePipe, name: "uiTranslate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: MemoizeFuncPipe, name: "memoizeFunc" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
243
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
244
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: GaussianChartComponent, isStandalone: true, selector: "ui-gaussian-chart", inputs: { score: "score", bestCandidateScore: "bestCandidateScore", applicationTheme: "applicationTheme", legendPosition: "legendPosition" }, ngImport: i0, template: "@if (score) {\n <div\n class=\"chart-section\"\n [attr.aria-label]=\"\n translationContext + 'ARIA_LABEL'\n | uiTranslate\n : {\n score: score,\n activeBucket: getScoreTranslationKey(score) | uiTranslate | async,\n bestCandidateScore: bestCandidateScore,\n activeBucketBestScore: getScoreTranslationKey(bestCandidateScore) | uiTranslate | async,\n }\n | async\n \"\n tabindex=\"0\"\n >\n <!-- Legend positioned at top -->\n @if (legendPosition === 'top-start' || legendPosition === 'top-end') {\n <ng-container [ngTemplateOutlet]=\"legendTemplate\"></ng-container>\n }\n <div class=\"chart-range-wrapper\">\n <div class=\"normal-chart-container\">\n <div class=\"normal-chart\">\n <canvas baseChart [data]=\"gaussianChartData\" [options]=\"gaussianChartOptions\" type=\"line\" class=\"chart\">\n </canvas>\n <div\n class=\"overlay-icon\"\n [style.bottom]=\"[overlayYValue, 3, 'subtract'] | memoizeFunc: getCalcPosition\"\n [style.left]=\"[overlayXValue, 20, 'subtract'] | memoizeFunc: getCalcPosition\"\n >\n <div class=\"drop-icon\">\n <ui-icon name=\"Pin-marker\" size=\"40\"></ui-icon>\n <span class=\"curve-score\">{{ score }}</span>\n </div>\n </div>\n <div\n class=\"best-score\"\n [style.height]=\"\n [100 - overlayYBestScoreValue, normalContainerPadding, 'add'] | memoizeFunc: getCalcPosition\n \"\n [style.bottom]=\"overlayYBestScoreValue + '%'\"\n [style.left]=\"overlayXBestScoreValue + '%'\"\n >\n <div\n class=\"best-score-content\"\n [style.left]=\"bestCandidateScore | memoizeFunc: getBestScoreContentPosition : this\"\n >\n <ui-icon name=\"Trophy\"></ui-icon>\n {{ bestCandidateScore }}\n </div>\n </div>\n </div>\n <div class=\"overlay\">\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.LOWEST\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.LOWEST\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWEST_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWEST' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.LOWER\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.LOWER\"\n [matTooltip]=\"(translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWER_TOOLTIP' | uiTranslate | async) || ''\"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.LOWER' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.AVERAGE\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.AVERAGE\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.AVERAGE_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.AVERAGE' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.HIGHER\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.HIGHER\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHER_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHER' | uiTranslate | async }}\n </div>\n </div>\n <div class=\"overlay-column\" [class.active]=\"activeBucket === PercentileThreshold.HIGHEST\">\n <div\n class=\"column-item\"\n [class.text-bold]=\"activeBucket === PercentileThreshold.HIGHEST\"\n [matTooltip]=\"\n (translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHEST_TOOLTIP' | uiTranslate | async) || ''\n \"\n >\n {{ translationContext + 'PERCENTAGE_BUCKETS_GRAPH.HIGHEST' | uiTranslate | async }}\n </div>\n </div>\n </div>\n </div>\n <div class=\"range\">\n <div>1</div>\n <div>20</div>\n <div>40</div>\n <div>60</div>\n <div>80</div>\n <div>99</div>\n </div>\n </div>\n <!-- Legend positioned at bottom -->\n @if (legendPosition === 'bottom-start' || legendPosition === 'bottom-end') {\n <ng-container [ngTemplateOutlet]=\"legendTemplate\"></ng-container>\n }\n </div>\n}\n\n<!-- Reusable legend template -->\n<ng-template #legendTemplate>\n <div class=\"legend-container\" [ngClass]=\"'legend-' + legendPosition\">\n <div class=\"legend\">\n <ui-icon name=\"Dot\" color=\"gray\"></ui-icon>\n {{ translationContext + 'CANDIDATE_SCORE' | uiTranslate | async }}\n </div>\n <div class=\"legend\">\n <ui-icon name=\"Trophy\" color=\"gray\"></ui-icon>\n {{ translationContext + 'HIGHEST_SCORE' | uiTranslate | async }}\n </div>\n </div>\n</ng-template>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}.chart-section{display:flex;flex-direction:column;gap:16px;width:100%}.chart-section .chart-range-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.chart-section .chart-range-wrapper .normal-chart-container{position:relative;padding-bottom:32px;padding-top:50px;border:1px solid #d3d3d3;border-radius:10px;width:100%;height:230px}.chart-section .chart-range-wrapper .normal-chart-container .normal-chart{position:relative;z-index:1;width:100%;height:100%}.chart-section .chart-range-wrapper .normal-chart-container .overlay{position:absolute;top:0;left:0;height:100%;width:100%;display:flex}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column{flex:1;font-size:12px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column .column-item{cursor:pointer}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column:not(:last-child){border-right:1px solid #d3d3d3}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active{background-color:#fff5ed;border-bottom:3px solid #242424}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child,.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child{border:none;position:relative}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child{border-right:1px solid #d3d3d3}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child:before,.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child:after{content:\"\";position:absolute;bottom:0;width:calc(100% - 4px);height:2.5px;background-color:#000}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child{border-top-left-radius:8px;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:first-child:before{right:0;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child{border-top-right-radius:8px;border-bottom-right-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column.active:last-child:after{left:0;border-bottom-left-radius:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay .overlay-column{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;padding-bottom:8px}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon{position:absolute;z-index:1;display:flex;flex-direction:column;align-items:center}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon .drop-icon{position:relative}.chart-section .chart-range-wrapper .normal-chart-container .overlay-icon .drop-icon .curve-score{font-size:14px;font-weight:700;position:absolute;width:100%;text-align:center;top:0;left:.5px;padding:4px 4px 9px}.chart-section .chart-range-wrapper .normal-chart-container .best-score{position:absolute;border-left:1px #242424 dashed}.chart-section .chart-range-wrapper .normal-chart-container .best-score .best-score-content{position:absolute;display:flex;gap:3px;align-items:center}.chart-section .chart-range-wrapper .range{display:flex;justify-content:space-between;color:#919191}.chart-section .chart-range-wrapper .range div{width:35px;text-align:center}.chart-section .chart-range-wrapper .range div:nth-child(2){text-align:left}.chart-section .chart-range-wrapper .range div:nth-last-child(2){text-align:right}.chart-section .legend-container{display:flex;gap:16px}.chart-section .legend-container.legend-top-start,.chart-section .legend-container.legend-bottom-start{justify-content:flex-start}.chart-section .legend-container.legend-top-end,.chart-section .legend-container.legend-bottom-end{justify-content:flex-end}.chart-section .legend-container .legend{display:flex;gap:8px;align-items:center;color:#666}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: BaseChartDirective, selector: "canvas[baseChart]", inputs: ["type", "legend", "data", "options", "plugins", "labels", "datasets"], outputs: ["chartClick", "chartHover"], exportAs: ["base-chart"] }, { kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i1.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: UiTranslatePipe, name: "uiTranslate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: MemoizeFuncPipe, name: "memoizeFunc" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
245
245
  }
246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponent, decorators: [{
246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponent, decorators: [{
247
247
  type: Component,
248
248
  args: [{ selector: 'ui-gaussian-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
249
249
  NgTemplateOutlet,
@@ -267,8 +267,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
267
267
 
268
268
  Chart.register(...registerables);
269
269
  class GaussianChartComponentModule {
270
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
271
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponentModule, imports: [NgClass,
270
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
271
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponentModule, imports: [NgClass,
272
272
  UiTranslatePipe,
273
273
  BaseChartDirective,
274
274
  MatTooltipModule,
@@ -276,12 +276,12 @@ class GaussianChartComponentModule {
276
276
  IconComponentModule,
277
277
  MemoizeFuncPipe,
278
278
  GaussianChartComponent], exports: [GaussianChartComponent] }); }
279
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponentModule, imports: [MatTooltipModule,
279
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponentModule, imports: [MatTooltipModule,
280
280
  CommonModule,
281
281
  IconComponentModule,
282
282
  GaussianChartComponent] }); }
283
283
  }
284
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: GaussianChartComponentModule, decorators: [{
284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: GaussianChartComponentModule, decorators: [{
285
285
  type: NgModule,
286
286
  args: [{
287
287
  exports: [GaussianChartComponent],
@@ -46,10 +46,10 @@ class IconLabelComponent {
46
46
  this.applicationTheme = defaultAppTheme;
47
47
  }
48
48
  }
49
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponent, deps: [{ token: 'CANOPYUI_DEFAULT_APPLICATION_THEME', optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
50
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.18", type: IconLabelComponent, isStandalone: true, selector: "ui-icon-label", inputs: { iconSize: "iconSize", iconName: "iconName", text: "text", iconColor: "iconColor", iconIndent: "iconIndent", applicationTheme: "applicationTheme" }, host: { properties: { "style.--icon-indent": "this.iconIndent" } }, ngImport: i0, template: "<ui-icon [name]=\"iconName\" [size]=\"iconSize\" [color]=\"iconColor\" aria-hidden=\"true\"></ui-icon>\n<span>{{ text }}</span>\n", styles: [":host{display:flex;align-items:center}:host ui-icon{margin-right:calc(var(--icon-indent) * 1px)}\n"], dependencies: [{ kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i1.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
49
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponent, deps: [{ token: 'CANOPYUI_DEFAULT_APPLICATION_THEME', optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
50
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: IconLabelComponent, isStandalone: true, selector: "ui-icon-label", inputs: { iconSize: "iconSize", iconName: "iconName", text: "text", iconColor: "iconColor", iconIndent: "iconIndent", applicationTheme: "applicationTheme" }, host: { properties: { "style.--icon-indent": "this.iconIndent" } }, ngImport: i0, template: "<ui-icon [name]=\"iconName\" [size]=\"iconSize\" [color]=\"iconColor\" aria-hidden=\"true\"></ui-icon>\n<span>{{ text }}</span>\n", styles: [":host{display:flex;align-items:center}:host ui-icon{margin-right:calc(var(--icon-indent) * 1px)}\n"], dependencies: [{ kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i1.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
51
51
  }
52
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponent, decorators: [{
52
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponent, decorators: [{
53
53
  type: Component,
54
54
  args: [{ selector: 'ui-icon-label', changeDetection: ChangeDetectionStrategy.OnPush, imports: [IconComponentModule], template: "<ui-icon [name]=\"iconName\" [size]=\"iconSize\" [color]=\"iconColor\" aria-hidden=\"true\"></ui-icon>\n<span>{{ text }}</span>\n", styles: [":host{display:flex;align-items:center}:host ui-icon{margin-right:calc(var(--icon-indent) * 1px)}\n"] }]
55
55
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -75,11 +75,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
75
75
  }] } });
76
76
 
77
77
  class IconLabelComponentModule {
78
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
79
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponentModule, imports: [CommonModule, IconComponentModule, IconLabelComponent], exports: [IconLabelComponent] }); }
80
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponentModule, imports: [CommonModule, IconComponentModule, IconLabelComponent] }); }
78
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
79
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponentModule, imports: [CommonModule, IconComponentModule, IconLabelComponent], exports: [IconLabelComponent] }); }
80
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponentModule, imports: [CommonModule, IconComponentModule, IconLabelComponent] }); }
81
81
  }
82
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconLabelComponentModule, decorators: [{
82
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconLabelComponentModule, decorators: [{
83
83
  type: NgModule,
84
84
  args: [{
85
85
  imports: [CommonModule, IconComponentModule, IconLabelComponent],
@@ -1588,10 +1588,10 @@ class IconsService {
1588
1588
  host.innerHTML = SHARED_SVG_DEFS;
1589
1589
  document.body.insertBefore(host.firstElementChild, document.body.firstChild);
1590
1590
  }
1591
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1592
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconsService, providedIn: 'root' }); }
1591
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1592
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconsService, providedIn: 'root' }); }
1593
1593
  }
1594
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconsService, decorators: [{
1594
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconsService, decorators: [{
1595
1595
  type: Injectable,
1596
1596
  args: [{
1597
1597
  providedIn: 'root',
@@ -1746,10 +1746,10 @@ class IconComponent {
1746
1746
  get isIconLoaded() {
1747
1747
  return this.iconsService.isIconLoaded(this._name);
1748
1748
  }
1749
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconComponent, deps: [{ token: 'CANOPYUI_DEFAULT_APPLICATION_THEME', optional: true }, { token: i1.MatIconRegistry }, { token: i2.DomSanitizer }, { token: IconsService }], target: i0.ɵɵFactoryTarget.Component }); }
1750
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: IconComponent, isStandalone: true, selector: "ui-icon", inputs: { size: "size", cssClass: "cssClass", name: "name", color: "color", filled: "filled", toggleIconStyle: "toggleIconStyle", applicationTheme: "applicationTheme", useFullIconName: "useFullIconName" }, host: { properties: { "style.--icon-size": "this.size" } }, usesOnChanges: true, ngImport: i0, template: "@if (isIconLoaded) {\n <mat-icon [svgIcon]=\"_name\" [attr.class]=\"customCssClass\" [ngStyle]=\"cssStyle\"></mat-icon>\n} @else {\n <div class=\"empty-icon-placeholder\"></div>\n}\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}.empty-icon-placeholder{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}mat-icon{display:flex;color:var(--icon-color)!important}mat-icon.size-16 svg{width:16px;height:16px}mat-icon.size-24 svg{width:24px;height:24px}mat-icon.size-40 svg{width:40px;height:40px}mat-icon.size-80 svg{width:80px;height:80px}mat-icon.dark svg{color:var(--cnp-icon-color, #888888)}mat-icon.white svg{color:var(--cnp-icon-color, #ffffff)}mat-icon.teal svg{color:var(--cnp-icon-color, #46a997)}mat-icon.petrol svg{color:var(--cnp-icon-color, #276678)}mat-icon.black svg{color:var(--cnp-icon-color, #000000)}mat-icon.red svg{color:var(--cnp-icon-color, #e02800)}mat-icon.gray svg,mat-icon.gray path{color:var(--cnp-icon-color, #666666);fill:var(--cnp-icon-color, #666666)}mat-icon.orange svg{color:var(--cnp-icon-color, #d07d00)}mat-icon.rebrand-black svg{color:var(--cnp-icon-color, #242424)}mat-icon.ai svg path{fill:url(#reusableAiInlineGradient) #d410aa}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1749
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconComponent, deps: [{ token: 'CANOPYUI_DEFAULT_APPLICATION_THEME', optional: true }, { token: i1.MatIconRegistry }, { token: i2.DomSanitizer }, { token: IconsService }], target: i0.ɵɵFactoryTarget.Component }); }
1750
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: IconComponent, isStandalone: true, selector: "ui-icon", inputs: { size: "size", cssClass: "cssClass", name: "name", color: "color", filled: "filled", toggleIconStyle: "toggleIconStyle", applicationTheme: "applicationTheme", useFullIconName: "useFullIconName" }, host: { properties: { "style.--icon-size": "this.size" } }, usesOnChanges: true, ngImport: i0, template: "@if (isIconLoaded) {\n <mat-icon [svgIcon]=\"_name\" [attr.class]=\"customCssClass\" [ngStyle]=\"cssStyle\"></mat-icon>\n} @else {\n <div class=\"empty-icon-placeholder\"></div>\n}\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}.empty-icon-placeholder{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}mat-icon{display:flex;color:var(--icon-color)!important}mat-icon.size-16 svg{width:16px;height:16px}mat-icon.size-24 svg{width:24px;height:24px}mat-icon.size-40 svg{width:40px;height:40px}mat-icon.size-80 svg{width:80px;height:80px}mat-icon.dark svg{color:var(--cnp-icon-color, #888888)}mat-icon.white svg{color:var(--cnp-icon-color, #ffffff)}mat-icon.teal svg{color:var(--cnp-icon-color, #46a997)}mat-icon.petrol svg{color:var(--cnp-icon-color, #276678)}mat-icon.black svg{color:var(--cnp-icon-color, #000000)}mat-icon.red svg{color:var(--cnp-icon-color, #e02800)}mat-icon.gray svg,mat-icon.gray path{color:var(--cnp-icon-color, #666666);fill:var(--cnp-icon-color, #666666)}mat-icon.orange svg{color:var(--cnp-icon-color, #d07d00)}mat-icon.rebrand-black svg{color:var(--cnp-icon-color, #242424)}mat-icon.ai svg path{fill:url(#reusableAiInlineGradient) #d410aa}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1751
1751
  }
1752
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconComponent, decorators: [{
1752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconComponent, decorators: [{
1753
1753
  type: Component,
1754
1754
  args: [{ selector: 'ui-icon', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [MatIcon, NgStyle], template: "@if (isIconLoaded) {\n <mat-icon [svgIcon]=\"_name\" [attr.class]=\"customCssClass\" [ngStyle]=\"cssStyle\"></mat-icon>\n} @else {\n <div class=\"empty-icon-placeholder\"></div>\n}\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}.empty-icon-placeholder{width:calc(var(--icon-size) * 1px)!important;height:calc(var(--icon-size) * 1px)!important}mat-icon{display:flex;color:var(--icon-color)!important}mat-icon.size-16 svg{width:16px;height:16px}mat-icon.size-24 svg{width:24px;height:24px}mat-icon.size-40 svg{width:40px;height:40px}mat-icon.size-80 svg{width:80px;height:80px}mat-icon.dark svg{color:var(--cnp-icon-color, #888888)}mat-icon.white svg{color:var(--cnp-icon-color, #ffffff)}mat-icon.teal svg{color:var(--cnp-icon-color, #46a997)}mat-icon.petrol svg{color:var(--cnp-icon-color, #276678)}mat-icon.black svg{color:var(--cnp-icon-color, #000000)}mat-icon.red svg{color:var(--cnp-icon-color, #e02800)}mat-icon.gray svg,mat-icon.gray path{color:var(--cnp-icon-color, #666666);fill:var(--cnp-icon-color, #666666)}mat-icon.orange svg{color:var(--cnp-icon-color, #d07d00)}mat-icon.rebrand-black svg{color:var(--cnp-icon-color, #242424)}mat-icon.ai svg path{fill:url(#reusableAiInlineGradient) #d410aa}\n"] }]
1755
1755
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -1779,11 +1779,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
1779
1779
  }] } });
1780
1780
 
1781
1781
  class IconComponentModule {
1782
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1783
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.18", ngImport: i0, type: IconComponentModule, imports: [CommonModule, MatIconModule, IconComponent], exports: [IconComponent] }); }
1784
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconComponentModule, providers: [provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule, MatIconModule, IconComponent] }); }
1782
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1783
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.19", ngImport: i0, type: IconComponentModule, imports: [CommonModule, MatIconModule, IconComponent], exports: [IconComponent] }); }
1784
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconComponentModule, providers: [provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule, MatIconModule, IconComponent] }); }
1785
1785
  }
1786
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: IconComponentModule, decorators: [{
1786
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconComponentModule, decorators: [{
1787
1787
  type: NgModule,
1788
1788
  args: [{
1789
1789
  imports: [CommonModule, MatIconModule, IconComponent],
@@ -100,8 +100,24 @@ class InfiniteScrollTableComponent {
100
100
  * the last — aligned between header and body regardless of browser/scrollbar behaviour.
101
101
  */
102
102
  this.scrollbarWidth = signal(0, ...(ngDevMode ? [{ debugName: "scrollbarWidth" }] : /* istanbul ignore next */ []));
103
+ /**
104
+ * Measured height (px) of the body viewport's horizontal scrollbar. When a short list also has a
105
+ * horizontal scrollbar, this is added to the viewport height so the scrollbar doesn't eat into the
106
+ * rows' vertical space and force a spurious vertical scrollbar. Mirrors `scrollbarWidth`.
107
+ */
108
+ this.hScrollbarHeight = signal(0, ...(ngDevMode ? [{ debugName: "hScrollbarHeight" }] : /* istanbul ignore next */ []));
103
109
  /** Guards `loadMore` to a single emission per approach to the end. */
104
110
  this.loadMoreArmed = true;
111
+ /**
112
+ * True when the browser can drive the header via a CSS scroll timeline (see the SCSS): the header
113
+ * then tracks the body's horizontal scroll on the compositor, with no per-frame main-thread work.
114
+ * In that case the JS `scrollLeft` sync is skipped so the offset isn't applied twice; it stays as
115
+ * the fallback for browsers without scroll-driven animations.
116
+ */
117
+ this.usesScrollTimelineHeaderSync = typeof CSS !== 'undefined' &&
118
+ CSS !== null &&
119
+ typeof CSS.supports === 'function' &&
120
+ CSS.supports('animation-timeline: scroll()');
105
121
  this.skeletonTheme = {
106
122
  background: '#F4F4F4',
107
123
  'border-radius': '4px',
@@ -143,8 +159,17 @@ class InfiniteScrollTableComponent {
143
159
  this.showEmptyState = computed(() => !this.loading() && !this.error() && !this.hasData(), ...(ngDevMode ? [{ debugName: "showEmptyState" }] : /* istanbul ignore next */ []));
144
160
  this.showErrorState = computed(() => !this.loading() && this.error() && !this.hasData(), ...(ngDevMode ? [{ debugName: "showErrorState" }] : /* istanbul ignore next */ []));
145
161
  this.showErrorFooter = computed(() => !this.loading() && this.error() && this.hasData(), ...(ngDevMode ? [{ debugName: "showErrorFooter" }] : /* istanbul ignore next */ []));
146
- /** Viewport height shrinks to the content and is capped at `maxHeight` (CSS `min()` mixes units). */
147
- this.viewportHeight = computed(() => `min(${this.renderRows().length * this.rowHeight()}px, ${this.maxHeight()})`, ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
162
+ /**
163
+ * Viewport height shrinks to the content and is capped at `maxHeight` (CSS `min()` mixes units).
164
+ * When a horizontal scrollbar is present it reserves that scrollbar's measured height on top of the
165
+ * content, so a short list doesn't overflow and grow a spurious vertical scrollbar. Still capped at
166
+ * `maxHeight`.
167
+ */
168
+ this.viewportHeight = computed(() => {
169
+ const contentHeight = this.renderRows().length * this.rowHeight();
170
+ const scrollbarReserve = this.horizontalScroll() ? this.hScrollbarHeight() : 0;
171
+ return `min(${contentHeight + scrollbarReserve}px, ${this.maxHeight()})`;
172
+ }, ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
148
173
  /** Screen-reader announcement for the busy states. */
149
174
  this.statusMessage = computed(() => {
150
175
  if (this.loading()) {
@@ -188,13 +213,25 @@ class InfiniteScrollTableComponent {
188
213
  const subscription = new Subscription();
189
214
  subscription.add(viewport.elementScrolled().subscribe(() => this.syncHorizontalScroll()));
190
215
  subscription.add(viewport.renderedRangeStream.subscribe(() => this.checkLoadMore()));
191
- // Keep the measured scrollbar width current: it changes when the vertical scrollbar appears
192
- // or disappears (content grows/shrinks) and on viewport resize.
193
- const measureScrollbar = () => this.scrollbarWidth.set(element.offsetWidth - element.clientWidth);
216
+ // Keep the measured scrollbar dimensions current: they change when a scrollbar appears or
217
+ // disappears (content grows/shrinks) and on viewport resize.
218
+ const measureScrollbar = () => {
219
+ this.scrollbarWidth.set(element.offsetWidth - element.clientWidth);
220
+ this.hScrollbarHeight.set(element.offsetHeight - element.clientHeight);
221
+ this.updateHeaderScrollMetric();
222
+ };
194
223
  subscription.add(viewport.renderedRangeStream.subscribe(() => measureScrollbar()));
224
+ // The viewport element's box can also change from things no signal captures — a flex/grid
225
+ // parent resizing, or a relative `maxHeight` (e.g. `70vh`) reacting to a container change.
226
+ // CDK caches its measured size, so re-measure the virtual viewport on any box change or it
227
+ // under-renders (empty tail band). The signal-driven height changes are covered by the
228
+ // dedicated effect below; this catches the rest.
195
229
  let resizeObserver;
196
230
  if (typeof ResizeObserver !== 'undefined') {
197
- resizeObserver = new ResizeObserver(() => measureScrollbar());
231
+ resizeObserver = new ResizeObserver(() => {
232
+ measureScrollbar();
233
+ this.scheduleViewportRemeasure();
234
+ });
198
235
  resizeObserver.observe(element);
199
236
  }
200
237
  measureScrollbar();
@@ -210,14 +247,31 @@ class InfiniteScrollTableComponent {
210
247
  onCleanup(() => {
211
248
  subscription.unsubscribe();
212
249
  resizeObserver?.disconnect();
213
- // Cancel a still-pending re-sync so it can't fire after the viewport leaves the DOM
250
+ // Cancel still-pending frames so they can't fire after the viewport leaves the DOM
214
251
  // (e.g. flipping to the empty/error state in the same tick).
215
252
  if (scrollSyncFrame !== undefined) {
216
253
  cancelAnimationFrame(scrollSyncFrame);
217
254
  }
255
+ if (this.remeasureFrame !== undefined) {
256
+ cancelAnimationFrame(this.remeasureFrame);
257
+ this.remeasureFrame = undefined;
258
+ }
218
259
  });
219
260
  });
220
261
  });
262
+ // Re-measure the CDK viewport whenever its height changes from a signal: data growth (more render
263
+ // rows), a runtime `rowHeight` change (also changes total content height), or a `maxHeight` change.
264
+ // `CdkVirtualScrollViewport` caches its measured size and only re-measures on scroll or window
265
+ // resize, so a runtime height increase would otherwise leave the extra space empty with the tail
266
+ // rows unrendered until a manual scroll/resize. Reading these signals (not `viewportHeight()`)
267
+ // keeps the dependency to genuine height inputs and off horizontal-scroll state.
268
+ effect(() => {
269
+ this.renderRows();
270
+ this.rowHeight();
271
+ this.maxHeight();
272
+ this.columns();
273
+ this.scheduleViewportRemeasure();
274
+ });
221
275
  // Re-arm the loadMore guard whenever the `data` input changes — a page arrived, or the set was
222
276
  // replaced (filter/search reset, even to a shorter or same-length list). It reads `data()` only,
223
277
  // NOT `loadingMore()`: a failed fetch clears `loadingMore` without changing `data`, so the guard
@@ -242,11 +296,13 @@ class InfiniteScrollTableComponent {
242
296
  return item[key];
243
297
  }
244
298
  /**
245
- * Content-independent flex-basis for a column: its declared width, else its min-width, else the
246
- * default. Using this (instead of `flex-basis: auto`) makes header and body cells size identically
247
- * so every column stays aligned regardless of the text inside header vs body cells.
299
+ * The single authoritative width for a column: its declared width, else its min-width, else the
300
+ * default. The template applies this identically as `flex-basis`, `min-width` AND `max-width` (with
301
+ * `flex-grow:0; flex-shrink:0; overflow:hidden`) to the header cell and every body cell, so a column
302
+ * is exactly this width in both containers — content is clipped and can never widen it. This is what
303
+ * keeps header and body columns aligned end-to-end regardless of cell content or horizontal scroll.
248
304
  */
249
- cellBasis(column) {
305
+ columnWidth(column) {
250
306
  return column.styles?.width ?? column.styles?.['min-width'] ?? '160px';
251
307
  }
252
308
  onRowClick(row) {
@@ -285,6 +341,38 @@ class InfiniteScrollTableComponent {
285
341
  event.preventDefault();
286
342
  this.onRowClick(row);
287
343
  }
344
+ /**
345
+ * Re-measure the CDK virtual viewport after its box may have changed. Deferred to the next frame so
346
+ * it reads the settled layout and never fires a "ResizeObserver loop limit exceeded" warning when
347
+ * driven from the ResizeObserver; repeated triggers coalesce to a single measure. The re-measure is
348
+ * what makes CDK recompute the rendered range to fill a viewport whose height grew at runtime.
349
+ */
350
+ scheduleViewportRemeasure() {
351
+ if (typeof requestAnimationFrame === 'undefined') {
352
+ this.viewport()?.checkViewportSize();
353
+ return;
354
+ }
355
+ if (this.remeasureFrame !== undefined) {
356
+ cancelAnimationFrame(this.remeasureFrame);
357
+ }
358
+ this.remeasureFrame = requestAnimationFrame(() => {
359
+ this.remeasureFrame = undefined;
360
+ // `viewport()` is null in the empty/error states and after teardown, so this safely no-ops.
361
+ this.viewport()?.checkViewportSize();
362
+ this.updateHeaderScrollMetric();
363
+ });
364
+ }
365
+ updateHeaderScrollMetric() {
366
+ if (!this.usesScrollTimelineHeaderSync) {
367
+ return;
368
+ }
369
+ const headerScroll = this.headerScroll()?.nativeElement;
370
+ if (!headerScroll) {
371
+ return;
372
+ }
373
+ const maxScroll = Math.max(0, headerScroll.scrollWidth - headerScroll.clientWidth);
374
+ headerScroll.style.setProperty('--ui-ist-header-scroll-max', `${maxScroll}px`);
375
+ }
288
376
  onRetry() {
289
377
  this.retry.emit();
290
378
  }
@@ -297,8 +385,8 @@ class InfiniteScrollTableComponent {
297
385
  const left = viewport.measureScrollOffset('left');
298
386
  const right = viewport.measureScrollOffset('right');
299
387
  const header = this.headerScroll();
300
- if (header) {
301
- header.nativeElement.scrollLeft = left;
388
+ if (header && !this.usesScrollTimelineHeaderSync) {
389
+ header.nativeElement.scrollLeft = Math.round(left);
302
390
  }
303
391
  this.scrollStart.set(left <= 1);
304
392
  this.scrollEnd.set(right <= 1);
@@ -333,10 +421,10 @@ class InfiniteScrollTableComponent {
333
421
  this.loadMore.emit();
334
422
  }
335
423
  }
336
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
337
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: InfiniteScrollTableComponent, isStandalone: true, selector: "ui-infinite-scroll-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, isCondensed: { classPropertyName: "isCondensed", publicName: "isCondensed", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, skeletonRowCount: { classPropertyName: "skeletonRowCount", publicName: "skeletonRowCount", isSignal: true, isRequired: false, transformFunction: null }, loadMoreThreshold: { classPropertyName: "loadMoreThreshold", publicName: "loadMoreThreshold", isSignal: true, isRequired: false, transformFunction: null }, noDataTemplate: { classPropertyName: "noDataTemplate", publicName: "noDataTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadMore: "loadMore", retry: "retry", rowClick: "rowClick", selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }, { propertyName: "headerScroll", first: true, predicate: ["headerScroll"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned),\n and its horizontal scrollLeft is synced from the body so columns stay aligned. -->\n <div\n #headerScroll\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.margin-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:1;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell:last-child{padding-right:24px}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: SkeletonComponent, selector: "ui-skeleton", inputs: ["count", "theme", "appearance", "isAiTheme", "applicationTheme"] }, { kind: "component", type: CheckboxComponent, selector: "ui-checkbox", inputs: ["disabled", "checked", "indeterminate", "companyColor", "name", "label", "multiple", "applicationTheme", "ariaLabel", "ariaRequired", "hasError", "hideBuiltInErrors", "hideLabelInErrors", "ariaLabelledby", "ariaDescribedby", "truncateText", "alignment", "tabIndex"], outputs: ["changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
424
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
425
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InfiniteScrollTableComponent, isStandalone: true, selector: "ui-infinite-scroll-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, isCondensed: { classPropertyName: "isCondensed", publicName: "isCondensed", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, skeletonRowCount: { classPropertyName: "skeletonRowCount", publicName: "skeletonRowCount", isSignal: true, isRequired: false, transformFunction: null }, loadMoreThreshold: { classPropertyName: "loadMoreThreshold", publicName: "loadMoreThreshold", isSignal: true, isRequired: false, transformFunction: null }, noDataTemplate: { classPropertyName: "noDataTemplate", publicName: "noDataTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadMore: "loadMore", retry: "retry", rowClick: "rowClick", selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }, { propertyName: "headerScroll", first: true, predicate: ["headerScroll"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned).\n The outer element reserves the body's vertical-scrollbar width as right padding, so the reserved\n strip keeps the header background and bottom border; the inner element carries the horizontal\n scrollLeft synced from the body so columns stay aligned. -->\n <div\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.padding-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div #headerScroll class=\"ui-ist__header-scroll\" role=\"presentation\">\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__header-scroll{overflow:hidden}@supports (animation-timeline: scroll()){.ui-ist{timeline-scope:--ui-ist-header-x}.ui-ist__body{scroll-timeline:--ui-ist-header-x x}.ui-ist__row--header .ui-ist__cell--header:not(.ui-ist__cell--sticky-start):not(.ui-ist__cell--sticky-end){animation:ui-ist-header-follow linear both;animation-timeline:--ui-ist-header-x}}@keyframes ui-ist-header-follow{to{transform:translate(calc(-1 * var(--ui-ist-header-scroll-max, 0px)))}}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:0;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2;order:1}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell--spacer{flex:1 1 auto;min-width:0;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell--sticky-end{padding-right:24px}.ui-ist--condensed .ui-ist__cell--spacer{padding:0}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: SkeletonComponent, selector: "ui-skeleton", inputs: ["count", "theme", "appearance", "isAiTheme", "applicationTheme"] }, { kind: "component", type: CheckboxComponent, selector: "ui-checkbox", inputs: ["disabled", "checked", "indeterminate", "companyColor", "name", "label", "multiple", "applicationTheme", "ariaLabel", "ariaRequired", "hasError", "hideBuiltInErrors", "hideLabelInErrors", "ariaLabelledby", "ariaDescribedby", "truncateText", "alignment", "tabIndex"], outputs: ["changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
338
426
  }
339
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponent, decorators: [{
427
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponent, decorators: [{
340
428
  type: Component,
341
429
  args: [{ selector: 'ui-infinite-scroll-table', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
342
430
  NgTemplateOutlet,
@@ -345,15 +433,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
345
433
  CdkVirtualForOf,
346
434
  SkeletonComponent,
347
435
  CheckboxComponent,
348
- ], template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned),\n and its horizontal scrollLeft is synced from the body so columns stay aligned. -->\n <div\n #headerScroll\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.margin-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"cellBasis(column)\"\n [style.min-width]=\"column.styles?.['min-width']\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:1;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell:last-child{padding-right:24px}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
436
+ ], template: "<div\n class=\"ui-ist\"\n role=\"table\"\n [class.ui-ist--condensed]=\"isCondensed()\"\n [class.ui-ist--scrolled-start]=\"!scrollStart()\"\n [class.ui-ist--scrolled-end]=\"horizontalScroll() && !scrollEnd()\"\n [attr.aria-rowcount]=\"hasMore() ? -1 : data().length + 1\"\n [attr.aria-busy]=\"loading() || loadingMore()\"\n>\n <!-- Header: a separate element above the viewport. It never scrolls vertically (stays pinned).\n The outer element reserves the body's vertical-scrollbar width as right padding, so the reserved\n strip keeps the header background and bottom border; the inner element carries the horizontal\n scrollLeft synced from the body so columns stay aligned. -->\n <div\n class=\"ui-ist__header\"\n [class.ui-ist__header--sticky]=\"stickyHeader()\"\n [style.padding-right.px]=\"scrollbarWidth()\"\n role=\"presentation\"\n >\n <div #headerScroll class=\"ui-ist__header-scroll\" role=\"presentation\">\n <div class=\"ui-ist__row ui-ist__row--header\" role=\"row\" aria-rowindex=\"1\">\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"columnheader\"\n ></div>\n }\n @for (column of columns(); track column.key; let colIndex = $index) {\n <div\n class=\"ui-ist__cell ui-ist__cell--header\"\n role=\"columnheader\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (column.headerCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.headerCellTemplate; context: { $implicit: column.title, column, colIndex }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ column.title }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </div>\n </div>\n\n <!-- Body: the CDK viewport owns BOTH vertical (virtualized) and horizontal scroll, so sticky\n columns pin against it and the horizontal scrollbar sits at the viewport bottom. -->\n @if (showViewport()) {\n <cdk-virtual-scroll-viewport\n class=\"ui-ist__body\"\n role=\"rowgroup\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"viewportHeight()\"\n >\n <div\n *cdkVirtualFor=\"let row of renderRows(); let rowIndex = index; trackBy: renderRowTrackBy\"\n class=\"ui-ist__row\"\n role=\"row\"\n [class.ui-ist__row--clickable]=\"row.kind === 'data'\"\n [class.ui-ist__row--selected]=\"isRowSelected(row)\"\n [attr.aria-selected]=\"isRowSelected(row) ? true : null\"\n [attr.aria-rowindex]=\"row.kind === 'data' ? row.index + 2 : null\"\n [attr.aria-hidden]=\"row.kind === 'skeleton' ? true : null\"\n [attr.tabindex]=\"row.kind === 'data' ? 0 : null\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"onRowClick(row)\"\n (keydown.enter)=\"onRowActivate($event, row)\"\n (keydown.space)=\"onRowActivate($event, row)\"\n >\n @if (selectable()) {\n <div\n class=\"ui-ist__cell ui-ist__cell--checkbox ui-ist__cell--sticky-start\"\n role=\"cell\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n @if (row.kind === 'data') {\n <ui-checkbox\n [checked]=\"isRowSelected(row)\"\n [ariaLabel]=\"'Select row ' + (row.index + 1)\"\n (changed)=\"onSelectionToggle(row, $event)\"\n ></ui-checkbox>\n }\n </div>\n }\n @for (column of columns(); track column.key) {\n <div\n class=\"ui-ist__cell\"\n role=\"cell\"\n [class.ui-ist__cell--sticky-start]=\"column.key === firstStickyKey()\"\n [class.ui-ist__cell--sticky-end]=\"column.key === lastStickyKey()\"\n [class.ui-ist__cell--right]=\"column.styles?.alignment === 'right'\"\n [class.ui-ist__cell--center]=\"column.styles?.alignment === 'center'\"\n [style.flex-basis]=\"columnWidth(column)\"\n [style.min-width]=\"columnWidth(column)\"\n [style.max-width]=\"columnWidth(column)\"\n [style.left.px]=\"stickyStartOffset(column)\"\n >\n @if (row.kind === 'skeleton') {\n <ui-skeleton class=\"ui-ist__skeleton\" [count]=\"1\" [theme]=\"skeletonTheme\" appearance=\"line\"></ui-skeleton>\n } @else if (column.rowCellTemplate) {\n <ng-container\n *ngTemplateOutlet=\"column.rowCellTemplate; context: { $implicit: row.item, rowIndex: row.index }\"\n ></ng-container>\n } @else {\n <span class=\"ui-ist__cell-text\">{{ getCellValue(row.item, column.key) }}</span>\n }\n </div>\n }\n <div class=\"ui-ist__cell ui-ist__cell--spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n </div>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Empty and error states render the consumer template in-frame below the header, mirroring how\n ui-table drops `noDataRowTpl` into the table body. Mid-scroll errors sit below the loaded rows. -->\n @if (showErrorFooter() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showErrorState() && errorTemplate(); as errorTpl) {\n <div class=\"ui-ist__state\" role=\"alert\">\n <ng-container *ngTemplateOutlet=\"errorTpl; context: errorContext\"></ng-container>\n </div>\n }\n\n @if (showEmptyState() && noDataTemplate(); as emptyTpl) {\n <div class=\"ui-ist__state\">\n <ng-container *ngTemplateOutlet=\"emptyTpl\"></ng-container>\n </div>\n }\n\n <span class=\"ui-ist__sr-only\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</span>\n</div>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{display:block}.ui-ist{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden;background:#fff}.ui-ist__header{flex:0 0 auto;box-sizing:border-box;overflow:hidden;border-bottom:1px solid #e0e0e0;background:#fff}.ui-ist__header--sticky{position:sticky;top:0;z-index:3}.ui-ist__header-scroll{overflow:hidden}@supports (animation-timeline: scroll()){.ui-ist{timeline-scope:--ui-ist-header-x}.ui-ist__body{scroll-timeline:--ui-ist-header-x x}.ui-ist__row--header .ui-ist__cell--header:not(.ui-ist__cell--sticky-start):not(.ui-ist__cell--sticky-end){animation:ui-ist-header-follow linear both;animation-timeline:--ui-ist-header-x}}@keyframes ui-ist-header-follow{to{transform:translate(calc(-1 * var(--ui-ist-header-scroll-max, 0px)))}}.ui-ist__body{flex:1 1 auto;overflow:auto;scrollbar-width:auto}.ui-ist__body::-webkit-scrollbar{width:8px;height:8px}.ui-ist__body::-webkit-scrollbar-button{display:none}.ui-ist__body::-webkit-scrollbar-thumb{background-color:#00000059;border-radius:4px}.ui-ist__body::-webkit-scrollbar-track:hover{background-color:#00000026}.ui-ist__row{display:flex;width:max-content;min-width:100%;box-sizing:border-box}.ui-ist__row--header{min-height:56px}.ui-ist__row:not(.ui-ist__row--header){border-bottom:1px solid #d3d3d3}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover{background:#fff2fc}.ui-ist__row--clickable:not(.ui-ist__row--selected):hover .ui-ist__cell{background:#fff2fc}.ui-ist__row--selected .ui-ist__cell{background:#f4f4f4}.ui-ist__cell{flex-grow:0;flex-shrink:0;box-sizing:border-box;display:flex;align-items:center;min-width:160px;padding:8px 24px;font-size:14px;line-height:20px;overflow:hidden;background:#fff}.ui-ist__cell--header{background:#fff;font-weight:700;font-size:14px;line-height:16px}.ui-ist__cell--right{justify-content:flex-end;text-align:right}.ui-ist__cell--center{justify-content:center;text-align:center}.ui-ist__cell--sticky-start{position:sticky;left:0;z-index:2}.ui-ist__cell--sticky-end{position:sticky;right:0;z-index:2;order:1}.ui-ist__cell--checkbox{flex:0 0 56px;min-width:56px;justify-content:center;padding:0}.ui-ist__cell--spacer{flex:1 1 auto;min-width:0;padding:0}.ui-ist__cell-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ui-ist__skeleton{display:block;width:100%}.ui-ist--scrolled-start .ui-ist__cell--sticky-start{box-shadow:24px 8px 24px #24242414}.ui-ist--scrolled-end .ui-ist__cell--sticky-end{box-shadow:0 8px 24px 4px #24242414}.ui-ist__state{padding:8px 24px;font-size:14px;line-height:20px}.ui-ist--condensed .ui-ist__cell{padding:8px 12px}.ui-ist--condensed .ui-ist__cell:first-child{padding-left:24px}.ui-ist--condensed .ui-ist__cell--sticky-end{padding-right:24px}.ui-ist--condensed .ui-ist__cell--spacer{padding:0}.ui-ist__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
349
437
  }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: true }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], rowIdKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdKey", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], isCondensed: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCondensed", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMore", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], skeletonRowCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRowCount", required: false }] }], loadMoreThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadMoreThreshold", required: false }] }], noDataTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noDataTemplate", required: false }] }], errorTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTemplate", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], retry: [{ type: i0.Output, args: ["retry"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], headerScroll: [{ type: i0.ViewChild, args: ['headerScroll', { isSignal: true }] }] } });
350
438
 
351
439
  class InfiniteScrollTableComponentModule {
352
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
353
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponentModule, imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent], exports: [InfiniteScrollTableComponent] }); }
354
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponentModule, imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent] }); }
440
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
441
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponentModule, imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent], exports: [InfiniteScrollTableComponent] }); }
442
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponentModule, imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent] }); }
355
443
  }
356
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: InfiniteScrollTableComponentModule, decorators: [{
444
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InfiniteScrollTableComponentModule, decorators: [{
357
445
  type: NgModule,
358
446
  args: [{
359
447
  imports: [CommonModule, ScrollingModule, InfiniteScrollTableComponent],