@weeehaoooz/talos-ui 0.1.0

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 (180) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -0
  3. package/fesm2022/weeehaoooz-talos-ui-button-button-group.mjs +237 -0
  4. package/fesm2022/weeehaoooz-talos-ui-button-button-group.mjs.map +1 -0
  5. package/fesm2022/weeehaoooz-talos-ui-button-button.mjs +93 -0
  6. package/fesm2022/weeehaoooz-talos-ui-button-button.mjs.map +1 -0
  7. package/fesm2022/weeehaoooz-talos-ui-core.mjs +438 -0
  8. package/fesm2022/weeehaoooz-talos-ui-core.mjs.map +1 -0
  9. package/fesm2022/weeehaoooz-talos-ui-data-display-badge.mjs +233 -0
  10. package/fesm2022/weeehaoooz-talos-ui-data-display-badge.mjs.map +1 -0
  11. package/fesm2022/weeehaoooz-talos-ui-data-display-status-tag.mjs +361 -0
  12. package/fesm2022/weeehaoooz-talos-ui-data-display-status-tag.mjs.map +1 -0
  13. package/fesm2022/weeehaoooz-talos-ui-data-display-timeline.mjs +312 -0
  14. package/fesm2022/weeehaoooz-talos-ui-data-display-timeline.mjs.map +1 -0
  15. package/fesm2022/weeehaoooz-talos-ui-data-display-trend-indicator.mjs +235 -0
  16. package/fesm2022/weeehaoooz-talos-ui-data-display-trend-indicator.mjs.map +1 -0
  17. package/fesm2022/weeehaoooz-talos-ui-data-viz-category-bar.mjs +462 -0
  18. package/fesm2022/weeehaoooz-talos-ui-data-viz-category-bar.mjs.map +1 -0
  19. package/fesm2022/weeehaoooz-talos-ui-data-viz-heatmap.mjs +805 -0
  20. package/fesm2022/weeehaoooz-talos-ui-data-viz-heatmap.mjs.map +1 -0
  21. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-donut.mjs +267 -0
  22. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-donut.mjs.map +1 -0
  23. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-gauge.mjs +351 -0
  24. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-gauge.mjs.map +1 -0
  25. package/fesm2022/weeehaoooz-talos-ui-data-viz-sparkline.mjs +566 -0
  26. package/fesm2022/weeehaoooz-talos-ui-data-viz-sparkline.mjs.map +1 -0
  27. package/fesm2022/weeehaoooz-talos-ui-feedback-alert.mjs +534 -0
  28. package/fesm2022/weeehaoooz-talos-ui-feedback-alert.mjs.map +1 -0
  29. package/fesm2022/weeehaoooz-talos-ui-feedback-dialog.mjs +446 -0
  30. package/fesm2022/weeehaoooz-talos-ui-feedback-dialog.mjs.map +1 -0
  31. package/fesm2022/weeehaoooz-talos-ui-feedback-snackbar.mjs +376 -0
  32. package/fesm2022/weeehaoooz-talos-ui-feedback-snackbar.mjs.map +1 -0
  33. package/fesm2022/weeehaoooz-talos-ui-feedback-tooltip.mjs +147 -0
  34. package/fesm2022/weeehaoooz-talos-ui-feedback-tooltip.mjs.map +1 -0
  35. package/fesm2022/weeehaoooz-talos-ui-form-affix.mjs +242 -0
  36. package/fesm2022/weeehaoooz-talos-ui-form-affix.mjs.map +1 -0
  37. package/fesm2022/weeehaoooz-talos-ui-form-autocomplete.mjs +514 -0
  38. package/fesm2022/weeehaoooz-talos-ui-form-autocomplete.mjs.map +1 -0
  39. package/fesm2022/weeehaoooz-talos-ui-form-checkbox.mjs +548 -0
  40. package/fesm2022/weeehaoooz-talos-ui-form-checkbox.mjs.map +1 -0
  41. package/fesm2022/weeehaoooz-talos-ui-form-chips.mjs +692 -0
  42. package/fesm2022/weeehaoooz-talos-ui-form-chips.mjs.map +1 -0
  43. package/fesm2022/weeehaoooz-talos-ui-form-color-picker.mjs +761 -0
  44. package/fesm2022/weeehaoooz-talos-ui-form-color-picker.mjs.map +1 -0
  45. package/fesm2022/weeehaoooz-talos-ui-form-date-picker.mjs +896 -0
  46. package/fesm2022/weeehaoooz-talos-ui-form-date-picker.mjs.map +1 -0
  47. package/fesm2022/weeehaoooz-talos-ui-form-date-range-picker.mjs +872 -0
  48. package/fesm2022/weeehaoooz-talos-ui-form-date-range-picker.mjs.map +1 -0
  49. package/fesm2022/weeehaoooz-talos-ui-form-date-time-picker.mjs +119 -0
  50. package/fesm2022/weeehaoooz-talos-ui-form-date-time-picker.mjs.map +1 -0
  51. package/fesm2022/weeehaoooz-talos-ui-form-date-time-range-picker.mjs +135 -0
  52. package/fesm2022/weeehaoooz-talos-ui-form-date-time-range-picker.mjs.map +1 -0
  53. package/fesm2022/weeehaoooz-talos-ui-form-drop-zone.mjs +666 -0
  54. package/fesm2022/weeehaoooz-talos-ui-form-drop-zone.mjs.map +1 -0
  55. package/fesm2022/weeehaoooz-talos-ui-form-form-field.mjs +147 -0
  56. package/fesm2022/weeehaoooz-talos-ui-form-form-field.mjs.map +1 -0
  57. package/fesm2022/weeehaoooz-talos-ui-form-input.mjs +33 -0
  58. package/fesm2022/weeehaoooz-talos-ui-form-input.mjs.map +1 -0
  59. package/fesm2022/weeehaoooz-talos-ui-form-otp.mjs +455 -0
  60. package/fesm2022/weeehaoooz-talos-ui-form-otp.mjs.map +1 -0
  61. package/fesm2022/weeehaoooz-talos-ui-form-password-input.mjs +379 -0
  62. package/fesm2022/weeehaoooz-talos-ui-form-password-input.mjs.map +1 -0
  63. package/fesm2022/weeehaoooz-talos-ui-form-radio.mjs +297 -0
  64. package/fesm2022/weeehaoooz-talos-ui-form-radio.mjs.map +1 -0
  65. package/fesm2022/weeehaoooz-talos-ui-form-range-input.mjs +661 -0
  66. package/fesm2022/weeehaoooz-talos-ui-form-range-input.mjs.map +1 -0
  67. package/fesm2022/weeehaoooz-talos-ui-form-rating.mjs +346 -0
  68. package/fesm2022/weeehaoooz-talos-ui-form-rating.mjs.map +1 -0
  69. package/fesm2022/weeehaoooz-talos-ui-form-select-input.mjs +896 -0
  70. package/fesm2022/weeehaoooz-talos-ui-form-select-input.mjs.map +1 -0
  71. package/fesm2022/weeehaoooz-talos-ui-form-slide-toggle.mjs +252 -0
  72. package/fesm2022/weeehaoooz-talos-ui-form-slide-toggle.mjs.map +1 -0
  73. package/fesm2022/weeehaoooz-talos-ui-form-transfer-list.mjs +916 -0
  74. package/fesm2022/weeehaoooz-talos-ui-form-transfer-list.mjs.map +1 -0
  75. package/fesm2022/weeehaoooz-talos-ui-layout.mjs +851 -0
  76. package/fesm2022/weeehaoooz-talos-ui-layout.mjs.map +1 -0
  77. package/fesm2022/weeehaoooz-talos-ui-nav.mjs +897 -0
  78. package/fesm2022/weeehaoooz-talos-ui-nav.mjs.map +1 -0
  79. package/fesm2022/weeehaoooz-talos-ui.mjs +17058 -0
  80. package/fesm2022/weeehaoooz-talos-ui.mjs.map +1 -0
  81. package/package.json +203 -0
  82. package/schematics/collection.json +10 -0
  83. package/schematics/ng-add/index.d.ts +3 -0
  84. package/schematics/ng-add/index.js +99 -0
  85. package/schematics/ng-add/schema.d.ts +10 -0
  86. package/schematics/ng-add/schema.js +2 -0
  87. package/schematics/ng-add/schema.json +52 -0
  88. package/styles/_alert.scss +56 -0
  89. package/styles/_badge.scss +279 -0
  90. package/styles/_button-group.scss +470 -0
  91. package/styles/_buttons.scss +442 -0
  92. package/styles/_card.scss +18 -0
  93. package/styles/_dialog.scss +116 -0
  94. package/styles/_drop-zone.scss +19 -0
  95. package/styles/_form-controls.scss +660 -0
  96. package/styles/_slide-toggle.scss +171 -0
  97. package/styles/_status-tag.scss +108 -0
  98. package/styles/_timeline.scss +19 -0
  99. package/styles/_tooltip.scss +32 -0
  100. package/styles/_typography.scss +279 -0
  101. package/styles/_variables.scss +590 -0
  102. package/styles/index.scss +15 -0
  103. package/types/weeehaoooz-talos-ui-button-button-group.d.ts +59 -0
  104. package/types/weeehaoooz-talos-ui-button-button-group.d.ts.map +1 -0
  105. package/types/weeehaoooz-talos-ui-button-button.d.ts +38 -0
  106. package/types/weeehaoooz-talos-ui-button-button.d.ts.map +1 -0
  107. package/types/weeehaoooz-talos-ui-core.d.ts +95 -0
  108. package/types/weeehaoooz-talos-ui-core.d.ts.map +1 -0
  109. package/types/weeehaoooz-talos-ui-data-display-badge.d.ts +119 -0
  110. package/types/weeehaoooz-talos-ui-data-display-badge.d.ts.map +1 -0
  111. package/types/weeehaoooz-talos-ui-data-display-status-tag.d.ts +135 -0
  112. package/types/weeehaoooz-talos-ui-data-display-status-tag.d.ts.map +1 -0
  113. package/types/weeehaoooz-talos-ui-data-display-timeline.d.ts +144 -0
  114. package/types/weeehaoooz-talos-ui-data-display-timeline.d.ts.map +1 -0
  115. package/types/weeehaoooz-talos-ui-data-display-trend-indicator.d.ts +83 -0
  116. package/types/weeehaoooz-talos-ui-data-display-trend-indicator.d.ts.map +1 -0
  117. package/types/weeehaoooz-talos-ui-data-viz-category-bar.d.ts +255 -0
  118. package/types/weeehaoooz-talos-ui-data-viz-category-bar.d.ts.map +1 -0
  119. package/types/weeehaoooz-talos-ui-data-viz-heatmap.d.ts +204 -0
  120. package/types/weeehaoooz-talos-ui-data-viz-heatmap.d.ts.map +1 -0
  121. package/types/weeehaoooz-talos-ui-data-viz-mini-donut.d.ts +101 -0
  122. package/types/weeehaoooz-talos-ui-data-viz-mini-donut.d.ts.map +1 -0
  123. package/types/weeehaoooz-talos-ui-data-viz-mini-gauge.d.ts +138 -0
  124. package/types/weeehaoooz-talos-ui-data-viz-mini-gauge.d.ts.map +1 -0
  125. package/types/weeehaoooz-talos-ui-data-viz-sparkline.d.ts +161 -0
  126. package/types/weeehaoooz-talos-ui-data-viz-sparkline.d.ts.map +1 -0
  127. package/types/weeehaoooz-talos-ui-feedback-alert.d.ts +212 -0
  128. package/types/weeehaoooz-talos-ui-feedback-alert.d.ts.map +1 -0
  129. package/types/weeehaoooz-talos-ui-feedback-dialog.d.ts +259 -0
  130. package/types/weeehaoooz-talos-ui-feedback-dialog.d.ts.map +1 -0
  131. package/types/weeehaoooz-talos-ui-feedback-snackbar.d.ts +147 -0
  132. package/types/weeehaoooz-talos-ui-feedback-snackbar.d.ts.map +1 -0
  133. package/types/weeehaoooz-talos-ui-feedback-tooltip.d.ts +32 -0
  134. package/types/weeehaoooz-talos-ui-feedback-tooltip.d.ts.map +1 -0
  135. package/types/weeehaoooz-talos-ui-form-affix.d.ts +88 -0
  136. package/types/weeehaoooz-talos-ui-form-affix.d.ts.map +1 -0
  137. package/types/weeehaoooz-talos-ui-form-autocomplete.d.ts +113 -0
  138. package/types/weeehaoooz-talos-ui-form-autocomplete.d.ts.map +1 -0
  139. package/types/weeehaoooz-talos-ui-form-checkbox.d.ts +165 -0
  140. package/types/weeehaoooz-talos-ui-form-checkbox.d.ts.map +1 -0
  141. package/types/weeehaoooz-talos-ui-form-chips.d.ts +152 -0
  142. package/types/weeehaoooz-talos-ui-form-chips.d.ts.map +1 -0
  143. package/types/weeehaoooz-talos-ui-form-color-picker.d.ts +144 -0
  144. package/types/weeehaoooz-talos-ui-form-color-picker.d.ts.map +1 -0
  145. package/types/weeehaoooz-talos-ui-form-date-picker.d.ts +138 -0
  146. package/types/weeehaoooz-talos-ui-form-date-picker.d.ts.map +1 -0
  147. package/types/weeehaoooz-talos-ui-form-date-range-picker.d.ts +148 -0
  148. package/types/weeehaoooz-talos-ui-form-date-range-picker.d.ts.map +1 -0
  149. package/types/weeehaoooz-talos-ui-form-date-time-picker.d.ts +44 -0
  150. package/types/weeehaoooz-talos-ui-form-date-time-picker.d.ts.map +1 -0
  151. package/types/weeehaoooz-talos-ui-form-date-time-range-picker.d.ts +48 -0
  152. package/types/weeehaoooz-talos-ui-form-date-time-range-picker.d.ts.map +1 -0
  153. package/types/weeehaoooz-talos-ui-form-drop-zone.d.ts +227 -0
  154. package/types/weeehaoooz-talos-ui-form-drop-zone.d.ts.map +1 -0
  155. package/types/weeehaoooz-talos-ui-form-form-field.d.ts +42 -0
  156. package/types/weeehaoooz-talos-ui-form-form-field.d.ts.map +1 -0
  157. package/types/weeehaoooz-talos-ui-form-input.d.ts +15 -0
  158. package/types/weeehaoooz-talos-ui-form-input.d.ts.map +1 -0
  159. package/types/weeehaoooz-talos-ui-form-otp.d.ts +111 -0
  160. package/types/weeehaoooz-talos-ui-form-otp.d.ts.map +1 -0
  161. package/types/weeehaoooz-talos-ui-form-password-input.d.ts +145 -0
  162. package/types/weeehaoooz-talos-ui-form-password-input.d.ts.map +1 -0
  163. package/types/weeehaoooz-talos-ui-form-radio.d.ts +84 -0
  164. package/types/weeehaoooz-talos-ui-form-radio.d.ts.map +1 -0
  165. package/types/weeehaoooz-talos-ui-form-range-input.d.ts +181 -0
  166. package/types/weeehaoooz-talos-ui-form-range-input.d.ts.map +1 -0
  167. package/types/weeehaoooz-talos-ui-form-rating.d.ts +110 -0
  168. package/types/weeehaoooz-talos-ui-form-rating.d.ts.map +1 -0
  169. package/types/weeehaoooz-talos-ui-form-select-input.d.ts +195 -0
  170. package/types/weeehaoooz-talos-ui-form-select-input.d.ts.map +1 -0
  171. package/types/weeehaoooz-talos-ui-form-slide-toggle.d.ts +79 -0
  172. package/types/weeehaoooz-talos-ui-form-slide-toggle.d.ts.map +1 -0
  173. package/types/weeehaoooz-talos-ui-form-transfer-list.d.ts +192 -0
  174. package/types/weeehaoooz-talos-ui-form-transfer-list.d.ts.map +1 -0
  175. package/types/weeehaoooz-talos-ui-layout.d.ts +286 -0
  176. package/types/weeehaoooz-talos-ui-layout.d.ts.map +1 -0
  177. package/types/weeehaoooz-talos-ui-nav.d.ts +384 -0
  178. package/types/weeehaoooz-talos-ui-nav.d.ts.map +1 -0
  179. package/types/weeehaoooz-talos-ui.d.ts +5050 -0
  180. package/types/weeehaoooz-talos-ui.d.ts.map +1 -0
@@ -0,0 +1,805 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, input, model, output, signal, computed, effect, Component, NgModule } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { LucideRefreshCw, LucideUpload, LucideMaximize2, LucideMinimize2, LucideChevronDown, LucideCheck, LucideFileSpreadsheet, LucideFileJson, LucideCalendar, LucideClock, LucideArrowLeftRight } from '@lucide/angular';
6
+ import { startOfDay, endOfDay, startOfISOWeek, subWeeks, endOfISOWeek, isSameDay, isBefore, addDays, addWeeks, isValid } from 'date-fns';
7
+ import { formatDate } from '@weeehaoooz/talos-ui/core';
8
+ import { DateRangePickerComponent } from '@weeehaoooz/talos-ui/form/date-range-picker';
9
+ import { TalosTooltipDirective } from '@weeehaoooz/talos-ui/feedback/tooltip';
10
+
11
+ const DEFAULT_DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
12
+ const PALETTE_CONFIG = {
13
+ indigo: {
14
+ zero: { bg: '#eef2ff', text: '#4338ca' },
15
+ min: { r: 219, g: 228, b: 255 }, // #dbe4ff
16
+ max: { r: 67, g: 56, b: 202 }, // #4338ca
17
+ gradientCss: 'linear-gradient(90deg, #dbe4ff 0%, #818cf8 50%, #4338ca 100%)'
18
+ },
19
+ blue: {
20
+ zero: { bg: '#eff6ff', text: '#1d4ed8' },
21
+ min: { r: 219, g: 234, b: 254 }, // #dbeafe
22
+ max: { r: 29, g: 78, b: 216 }, // #1d4ed8
23
+ gradientCss: 'linear-gradient(90deg, #dbeafe 0%, #60a5fa 50%, #1d4ed8 100%)'
24
+ },
25
+ emerald: {
26
+ zero: { bg: '#ecfdf5', text: '#047857' },
27
+ min: { r: 209, g: 250, b: 229 }, // #d1fae5
28
+ max: { r: 4, g: 120, b: 87 }, // #047857
29
+ gradientCss: 'linear-gradient(90deg, #d1fae5 0%, #34d399 50%, #047857 100%)'
30
+ },
31
+ rose: {
32
+ zero: { bg: '#fff1f2', text: '#be123c' },
33
+ min: { r: 255, g: 228, b: 230 }, // #ffe4e6
34
+ max: { r: 190, g: 18, b: 60 }, // #be123c
35
+ gradientCss: 'linear-gradient(90deg, #ffe4e6 0%, #fb7185 50%, #be123c 100%)'
36
+ },
37
+ amber: {
38
+ zero: { bg: '#fffbeb', text: '#b45309' },
39
+ min: { r: 254, g: 243, b: 199 }, // #fef3c7
40
+ max: { r: 180, g: 83, b: 9 }, // #b45309
41
+ gradientCss: 'linear-gradient(90deg, #fef3c7 0%, #fbbf24 50%, #b45309 100%)'
42
+ },
43
+ violet: {
44
+ zero: { bg: '#f5f3ff', text: '#6d28d9' },
45
+ min: { r: 237, g: 233, b: 254 }, // #ede9fe
46
+ max: { r: 109, g: 40, b: 217 }, // #6d28d9
47
+ gradientCss: 'linear-gradient(90deg, #ede9fe 0%, #a78bfa 50%, #6d28d9 100%)'
48
+ },
49
+ slate: {
50
+ zero: { bg: '#f8fafc', text: '#334155' },
51
+ min: { r: 226, g: 232, b: 240 }, // #e2e8f0
52
+ max: { r: 51, g: 65, b: 85 }, // #334155
53
+ gradientCss: 'linear-gradient(90deg, #e2e8f0 0%, #94a3b8 50%, #334155 100%)'
54
+ },
55
+ custom: {
56
+ zero: { bg: '#eef2ff', text: '#4338ca' },
57
+ min: { r: 219, g: 228, b: 255 },
58
+ max: { r: 67, g: 56, b: 202 },
59
+ gradientCss: 'linear-gradient(90deg, #dbe4ff 0%, #4338ca 100%)'
60
+ }
61
+ };
62
+ class TalosHeatmapComponent {
63
+ elementRef = inject(ElementRef);
64
+ // Inputs & Models
65
+ data = input([], /* @ts-ignore */
66
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
67
+ metrics = input([], /* @ts-ignore */
68
+ ...(ngDevMode ? [{ debugName: "metrics" }] : /* istanbul ignore next */ []));
69
+ selectedMetricId = model(undefined, /* @ts-ignore */
70
+ ...(ngDevMode ? [{ debugName: "selectedMetricId" }] : /* istanbul ignore next */ []));
71
+ interval = model('hour', /* @ts-ignore */
72
+ ...(ngDevMode ? [{ debugName: "interval" }] : /* istanbul ignore next */ []));
73
+ dateRange = model(null, /* @ts-ignore */
74
+ ...(ngDevMode ? [{ debugName: "dateRange" }] : /* istanbul ignore next */ []));
75
+ swapAxes = model(false, /* @ts-ignore */
76
+ ...(ngDevMode ? [{ debugName: "swapAxes" }] : /* istanbul ignore next */ []));
77
+ title = input('Busiest times', /* @ts-ignore */
78
+ ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
79
+ hoursRange = input([9, 17], /* @ts-ignore */
80
+ ...(ngDevMode ? [{ debugName: "hoursRange" }] : /* istanbul ignore next */ []));
81
+ timeFormat = input('12h', /* @ts-ignore */
82
+ ...(ngDevMode ? [{ debugName: "timeFormat" }] : /* istanbul ignore next */ []));
83
+ days = input(DEFAULT_DAYS, /* @ts-ignore */
84
+ ...(ngDevMode ? [{ debugName: "days" }] : /* istanbul ignore next */ []));
85
+ colorScheme = input('indigo', /* @ts-ignore */
86
+ ...(ngDevMode ? [{ debugName: "colorScheme" }] : /* istanbul ignore next */ []));
87
+ customColorStops = input(undefined, /* @ts-ignore */
88
+ ...(ngDevMode ? [{ debugName: "customColorStops" }] : /* istanbul ignore next */ []));
89
+ showLegend = input(true, /* @ts-ignore */
90
+ ...(ngDevMode ? [{ debugName: "showLegend" }] : /* istanbul ignore next */ []));
91
+ showValues = input(true, /* @ts-ignore */
92
+ ...(ngDevMode ? [{ debugName: "showValues" }] : /* istanbul ignore next */ []));
93
+ cellShape = input('pill', /* @ts-ignore */
94
+ ...(ngDevMode ? [{ debugName: "cellShape" }] : /* istanbul ignore next */ []));
95
+ cellSize = input('md', /* @ts-ignore */
96
+ ...(ngDevMode ? [{ debugName: "cellSize" }] : /* istanbul ignore next */ []));
97
+ fitWidth = input(undefined, /* @ts-ignore */
98
+ ...(ngDevMode ? [{ debugName: "fitWidth" }] : /* istanbul ignore next */ []));
99
+ loading = input(false, /* @ts-ignore */
100
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
101
+ showToolbar = input(true, /* @ts-ignore */
102
+ ...(ngDevMode ? [{ debugName: "showToolbar" }] : /* istanbul ignore next */ []));
103
+ showRefresh = input(true, /* @ts-ignore */
104
+ ...(ngDevMode ? [{ debugName: "showRefresh" }] : /* istanbul ignore next */ []));
105
+ showExport = input(true, /* @ts-ignore */
106
+ ...(ngDevMode ? [{ debugName: "showExport" }] : /* istanbul ignore next */ []));
107
+ showExpand = input(true, /* @ts-ignore */
108
+ ...(ngDevMode ? [{ debugName: "showExpand" }] : /* istanbul ignore next */ []));
109
+ showSwapAxes = input(false, /* @ts-ignore */
110
+ ...(ngDevMode ? [{ debugName: "showSwapAxes" }] : /* istanbul ignore next */ []));
111
+ showIntervalToggle = input(false, /* @ts-ignore */
112
+ ...(ngDevMode ? [{ debugName: "showIntervalToggle" }] : /* istanbul ignore next */ []));
113
+ showDateRangePicker = input(false, /* @ts-ignore */
114
+ ...(ngDevMode ? [{ debugName: "showDateRangePicker" }] : /* istanbul ignore next */ []));
115
+ dateRangePresets = input(null, /* @ts-ignore */
116
+ ...(ngDevMode ? [{ debugName: "dateRangePresets" }] : /* istanbul ignore next */ []));
117
+ unit = input('', /* @ts-ignore */
118
+ ...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
119
+ maxValue = input(undefined, /* @ts-ignore */
120
+ ...(ngDevMode ? [{ debugName: "maxValue" }] : /* istanbul ignore next */ []));
121
+ minValue = input(undefined, /* @ts-ignore */
122
+ ...(ngDevMode ? [{ debugName: "minValue" }] : /* istanbul ignore next */ []));
123
+ // Outputs
124
+ cellClick = output();
125
+ cellHover = output();
126
+ timeRangeChange = output();
127
+ refresh = output();
128
+ metricChange = output();
129
+ export = output();
130
+ // State signals
131
+ isExpanded = signal(false, /* @ts-ignore */
132
+ ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
133
+ isMetricDropdownOpen = signal(false, /* @ts-ignore */
134
+ ...(ngDevMode ? [{ debugName: "isMetricDropdownOpen" }] : /* istanbul ignore next */ []));
135
+ isExportDropdownOpen = signal(false, /* @ts-ignore */
136
+ ...(ngDevMode ? [{ debugName: "isExportDropdownOpen" }] : /* istanbul ignore next */ []));
137
+ hoveredCell = signal(null, /* @ts-ignore */
138
+ ...(ngDevMode ? [{ debugName: "hoveredCell" }] : /* istanbul ignore next */ []));
139
+ focusedCoord = signal(null, /* @ts-ignore */
140
+ ...(ngDevMode ? [{ debugName: "focusedCoord" }] : /* istanbul ignore next */ []));
141
+ // Layout Fit computation
142
+ isFitWidth = computed(() => {
143
+ const fw = this.fitWidth();
144
+ if (fw !== undefined)
145
+ return fw;
146
+ return this.cellShape() !== 'square';
147
+ }, /* @ts-ignore */
148
+ ...(ngDevMode ? [{ debugName: "isFitWidth" }] : /* istanbul ignore next */ []));
149
+ // Active Metric computation
150
+ currentMetric = computed(() => {
151
+ const list = this.metrics();
152
+ if (!list || list.length === 0)
153
+ return undefined;
154
+ const selectedId = this.selectedMetricId();
155
+ if (selectedId) {
156
+ const found = list.find((m) => m.id === selectedId);
157
+ if (found)
158
+ return found;
159
+ }
160
+ return list[0];
161
+ }, /* @ts-ignore */
162
+ ...(ngDevMode ? [{ debugName: "currentMetric" }] : /* istanbul ignore next */ []));
163
+ // Effective Active Color Scheme
164
+ activeColorScheme = computed(() => {
165
+ const metric = this.currentMetric();
166
+ if (metric && metric.colorScheme)
167
+ return metric.colorScheme;
168
+ return this.colorScheme();
169
+ }, /* @ts-ignore */
170
+ ...(ngDevMode ? [{ debugName: "activeColorScheme" }] : /* istanbul ignore next */ []));
171
+ // Effective Unit
172
+ activeUnit = computed(() => {
173
+ const metric = this.currentMetric();
174
+ if (metric && metric.unit !== undefined)
175
+ return metric.unit;
176
+ return this.unit();
177
+ }, /* @ts-ignore */
178
+ ...(ngDevMode ? [{ debugName: "activeUnit" }] : /* istanbul ignore next */ []));
179
+ // Effective Raw Data Input
180
+ activeDataInput = computed(() => {
181
+ const metric = this.currentMetric();
182
+ if (metric)
183
+ return metric.data;
184
+ return this.data();
185
+ }, /* @ts-ignore */
186
+ ...(ngDevMode ? [{ debugName: "activeDataInput" }] : /* istanbul ignore next */ []));
187
+ // Hours array from range (for hour-by-hour mode)
188
+ hours = computed(() => {
189
+ const [start, end] = this.hoursRange();
190
+ const clampedStart = Math.max(0, Math.min(23, start));
191
+ const clampedEnd = Math.max(clampedStart, Math.min(23, end));
192
+ const result = [];
193
+ for (let h = clampedStart; h <= clampedEnd; h++) {
194
+ result.push(h);
195
+ }
196
+ return result;
197
+ }, /* @ts-ignore */
198
+ ...(ngDevMode ? [{ debugName: "hours" }] : /* istanbul ignore next */ []));
199
+ // Resolved Date Range bounds
200
+ parsedDateRange = computed(() => {
201
+ const dr = this.dateRange();
202
+ if (!dr || (!dr.startDate && !dr.endDate)) {
203
+ return { start: null, end: null };
204
+ }
205
+ const s = dr.startDate ? startOfDay(new Date(dr.startDate)) : null;
206
+ const e = dr.endDate ? endOfDay(new Date(dr.endDate)) : (s ? endOfDay(s) : null);
207
+ return { start: s, end: e };
208
+ }, /* @ts-ignore */
209
+ ...(ngDevMode ? [{ debugName: "parsedDateRange" }] : /* istanbul ignore next */ []));
210
+ // Day list for Day-by-Day mode (weeks grouping)
211
+ dayModeWeeks = computed(() => {
212
+ const { start, end } = this.parsedDateRange();
213
+ const effectiveStart = start || startOfISOWeek(subWeeks(new Date(), 3));
214
+ const effectiveEnd = end || endOfISOWeek(new Date());
215
+ const weeks = [];
216
+ let currentWeekStart = startOfISOWeek(effectiveStart);
217
+ const lastWeekEnd = endOfISOWeek(effectiveEnd);
218
+ while (isSameDay(currentWeekStart, lastWeekEnd) || isBefore(currentWeekStart, lastWeekEnd)) {
219
+ const currentWeekEnd = addDays(currentWeekStart, 6);
220
+ const daysInWeek = [];
221
+ for (let i = 0; i < 7; i++) {
222
+ daysInWeek.push(addDays(currentWeekStart, i));
223
+ }
224
+ const label = `${formatDate(currentWeekStart, 'MMM d')} - ${formatDate(currentWeekEnd, 'MMM d')}`;
225
+ weeks.push({
226
+ label,
227
+ start: currentWeekStart,
228
+ end: currentWeekEnd,
229
+ days: daysInWeek
230
+ });
231
+ currentWeekStart = addWeeks(currentWeekStart, 1);
232
+ }
233
+ return weeks;
234
+ }, /* @ts-ignore */
235
+ ...(ngDevMode ? [{ debugName: "dayModeWeeks" }] : /* istanbul ignore next */ []));
236
+ // Normalized Value Map:
237
+ // For 'hour': Map<`${colKey}_${hour}`, { value, meta }>
238
+ // For 'day': Map<`${yyyy-MM-dd}`, { value, meta }> AND Map<`${colKey}`, { value, meta }>
239
+ normalizedValueMap = computed(() => {
240
+ const map = new Map();
241
+ const rawInput = this.activeDataInput();
242
+ const currentDays = this.days();
243
+ const currentInterval = this.interval();
244
+ if (!rawInput)
245
+ return map;
246
+ if (Array.isArray(rawInput)) {
247
+ if (rawInput.length === 0)
248
+ return map;
249
+ const firstItem = rawInput[0];
250
+ if (typeof firstItem === 'string' ||
251
+ firstItem instanceof Date ||
252
+ (typeof firstItem === 'number' && firstItem > 1000000000)) {
253
+ // Raw Timestamp list
254
+ rawInput.forEach((ts) => {
255
+ const date = new Date(ts);
256
+ if (isValid(date)) {
257
+ if (currentInterval === 'day') {
258
+ const dayKey = formatDate(date, 'yyyy-MM-dd');
259
+ const existing = map.get(dayKey);
260
+ if (existing)
261
+ existing.value += 1;
262
+ else
263
+ map.set(dayKey, { value: 1 });
264
+ }
265
+ else {
266
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
267
+ const dayName = dayNames[date.getDay()];
268
+ const matchedDay = currentDays.find((d) => d.toLowerCase().startsWith(dayName.toLowerCase())) || dayName;
269
+ const hour = date.getHours();
270
+ const key = `${matchedDay}_${hour}`;
271
+ const existing = map.get(key);
272
+ if (existing)
273
+ existing.value += 1;
274
+ else
275
+ map.set(key, { value: 1 });
276
+ }
277
+ }
278
+ });
279
+ }
280
+ else {
281
+ // HeatmapDataPoint array
282
+ rawInput.forEach((point) => {
283
+ if (currentInterval === 'day') {
284
+ let dayKey = '';
285
+ if (point.date) {
286
+ dayKey = typeof point.date === 'string' && /^\d{4}-\d{2}-\d{2}/.test(point.date)
287
+ ? point.date.substring(0, 10)
288
+ : formatDate(new Date(point.date), 'yyyy-MM-dd');
289
+ }
290
+ else if (point.day instanceof Date) {
291
+ dayKey = formatDate(point.day, 'yyyy-MM-dd');
292
+ }
293
+ else if (typeof point.day === 'string' && /^\d{4}-\d{2}-\d{2}/.test(point.day)) {
294
+ dayKey = point.day.substring(0, 10);
295
+ }
296
+ else {
297
+ dayKey = String(point.day ?? '');
298
+ }
299
+ if (dayKey) {
300
+ const existing = map.get(dayKey);
301
+ if (existing) {
302
+ existing.value += point.value;
303
+ if (point.meta)
304
+ existing.meta = { ...existing.meta, ...point.meta };
305
+ }
306
+ else {
307
+ map.set(dayKey, { value: point.value, meta: point.meta });
308
+ }
309
+ }
310
+ }
311
+ else {
312
+ // Hour by hour
313
+ let dayKey = '';
314
+ if (point.day instanceof Date) {
315
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
316
+ const dayName = dayNames[point.day.getDay()];
317
+ dayKey = currentDays.find((d) => d.toLowerCase().startsWith(dayName.toLowerCase())) || dayName;
318
+ }
319
+ else if (typeof point.day === 'number') {
320
+ dayKey = currentDays[point.day] || String(point.day);
321
+ }
322
+ else {
323
+ dayKey = String(point.day ?? '');
324
+ }
325
+ const hour = point.hour ?? 0;
326
+ const key = `${dayKey}_${hour}`;
327
+ const existing = map.get(key);
328
+ if (existing) {
329
+ existing.value += point.value;
330
+ if (point.meta)
331
+ existing.meta = { ...existing.meta, ...point.meta };
332
+ }
333
+ else {
334
+ map.set(key, { value: point.value, meta: point.meta });
335
+ }
336
+ }
337
+ });
338
+ }
339
+ }
340
+ else if (typeof rawInput === 'object') {
341
+ // HeatmapMatrixData
342
+ const matrix = rawInput;
343
+ Object.entries(matrix).forEach(([outerKey, innerObj]) => {
344
+ if (typeof innerObj === 'object' && innerObj !== null) {
345
+ Object.entries(innerObj).forEach(([innerKey, val]) => {
346
+ const numVal = Number(val) || 0;
347
+ if (currentInterval === 'day') {
348
+ const key = `${outerKey}_${innerKey}`;
349
+ map.set(key, { value: numVal });
350
+ }
351
+ else {
352
+ const isInnerHour = !isNaN(Number(innerKey));
353
+ if (isInnerHour) {
354
+ const hour = Number(innerKey);
355
+ const key = `${outerKey}_${hour}`;
356
+ map.set(key, { value: numVal });
357
+ }
358
+ else {
359
+ const hour = Number(outerKey);
360
+ const key = `${innerKey}_${hour}`;
361
+ map.set(key, { value: numVal });
362
+ }
363
+ }
364
+ });
365
+ }
366
+ });
367
+ }
368
+ return map;
369
+ }, /* @ts-ignore */
370
+ ...(ngDevMode ? [{ debugName: "normalizedValueMap" }] : /* istanbul ignore next */ []));
371
+ // Effective min & max value for heat scale
372
+ computedScaleBounds = computed(() => {
373
+ const customMin = this.minValue();
374
+ const customMax = this.maxValue();
375
+ const map = this.normalizedValueMap();
376
+ let dataMax = 0;
377
+ for (const item of map.values()) {
378
+ if (item.value > dataMax)
379
+ dataMax = item.value;
380
+ }
381
+ const min = customMin !== undefined ? customMin : 0;
382
+ const max = customMax !== undefined ? customMax : Math.max(1, dataMax);
383
+ return { min, max };
384
+ }, /* @ts-ignore */
385
+ ...(ngDevMode ? [{ debugName: "computedScaleBounds" }] : /* istanbul ignore next */ []));
386
+ // Gradient CSS for Legend bar
387
+ legendGradientCss = computed(() => {
388
+ const scheme = this.activeColorScheme();
389
+ return PALETTE_CONFIG[scheme]?.gradientCss || PALETTE_CONFIG.indigo.gradientCss;
390
+ }, /* @ts-ignore */
391
+ ...(ngDevMode ? [{ debugName: "legendGradientCss" }] : /* istanbul ignore next */ []));
392
+ // Column Headers computation (supports axis swapping)
393
+ columnHeaders = computed(() => {
394
+ const isSwapped = this.swapAxes();
395
+ const currentInterval = this.interval();
396
+ if (!isSwapped) {
397
+ return this.days().map((day) => ({ key: day, label: day }));
398
+ }
399
+ // When axes are swapped:
400
+ if (currentInterval === 'day') {
401
+ const weeks = this.dayModeWeeks();
402
+ return weeks.map((w) => ({ key: w.label, label: w.label }));
403
+ }
404
+ const hoursList = this.hours();
405
+ const format = this.timeFormat();
406
+ return hoursList.map((hour) => ({
407
+ key: hour,
408
+ label: this.formatHourLabel(hour, format)
409
+ }));
410
+ }, /* @ts-ignore */
411
+ ...(ngDevMode ? [{ debugName: "columnHeaders" }] : /* istanbul ignore next */ []));
412
+ // Grid Matrix computation
413
+ gridRows = computed(() => {
414
+ const currentInterval = this.interval();
415
+ const isSwapped = this.swapAxes();
416
+ const map = this.normalizedValueMap();
417
+ const { min, max } = this.computedScaleBounds();
418
+ const scheme = this.activeColorScheme();
419
+ const palette = PALETTE_CONFIG[scheme] || PALETTE_CONFIG.indigo;
420
+ const unitStr = this.activeUnit();
421
+ const unitSuffix = unitStr ? ` ${unitStr}` : '';
422
+ const format = this.timeFormat();
423
+ const getVisuals = (val) => {
424
+ const intensity = max > min ? Math.max(0, Math.min(1, (val - min) / (max - min))) : 0;
425
+ let bgColor = '';
426
+ let textColor = '';
427
+ if (val === 0) {
428
+ bgColor = palette.zero.bg;
429
+ textColor = palette.zero.text;
430
+ }
431
+ else {
432
+ const r = Math.round(palette.min.r + (palette.max.r - palette.min.r) * intensity);
433
+ const g = Math.round(palette.min.g + (palette.max.g - palette.min.g) * intensity);
434
+ const b = Math.round(palette.min.b + (palette.max.b - palette.min.b) * intensity);
435
+ bgColor = `rgb(${r}, ${g}, ${b})`;
436
+ textColor = intensity >= 0.55 ? '#ffffff' : palette.zero.text;
437
+ }
438
+ return { intensity, bgColor, textColor };
439
+ };
440
+ // --- DAY-BY-DAY MODE ---
441
+ if (currentInterval === 'day') {
442
+ const weeks = this.dayModeWeeks();
443
+ const dayLabels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
444
+ if (!isSwapped) {
445
+ // Standard: Rows = Weeks, Columns = Days
446
+ return weeks.map((week, weekIdx) => {
447
+ const cells = week.days.map((d, dayIdx) => {
448
+ const dateStr = formatDate(d, 'yyyy-MM-dd');
449
+ const dayName = dayLabels[dayIdx];
450
+ const entry = map.get(dateStr) || map.get(`${dayName}_${weekIdx}`);
451
+ const val = entry?.value ?? 0;
452
+ const { intensity, bgColor, textColor } = getVisuals(val);
453
+ const tooltip = `${formatDate(d, 'EEEE, MMMM d, yyyy')}: ${val}${unitSuffix}`;
454
+ return {
455
+ id: dateStr,
456
+ colKey: dayName,
457
+ colLabel: `${dayName} (${formatDate(d, 'd')})`,
458
+ rowKey: week.label,
459
+ rowLabel: week.label,
460
+ value: val,
461
+ intensity,
462
+ backgroundColor: bgColor,
463
+ textColor,
464
+ formattedValue: String(val),
465
+ tooltipText: tooltip,
466
+ date: d,
467
+ meta: entry?.meta
468
+ };
469
+ });
470
+ return {
471
+ key: week.label,
472
+ label: week.label,
473
+ cells
474
+ };
475
+ });
476
+ }
477
+ else {
478
+ // Swapped: Rows = Days (Mon..Sun), Columns = Weeks
479
+ return dayLabels.map((dayName, dayIdx) => {
480
+ const cells = weeks.map((week, weekIdx) => {
481
+ const d = week.days[dayIdx];
482
+ const dateStr = formatDate(d, 'yyyy-MM-dd');
483
+ const entry = map.get(dateStr) || map.get(`${dayName}_${weekIdx}`);
484
+ const val = entry?.value ?? 0;
485
+ const { intensity, bgColor, textColor } = getVisuals(val);
486
+ const tooltip = `${formatDate(d, 'EEEE, MMMM d, yyyy')}: ${val}${unitSuffix}`;
487
+ return {
488
+ id: `${dateStr}_swapped`,
489
+ colKey: week.label,
490
+ colLabel: week.label,
491
+ rowKey: dayName,
492
+ rowLabel: dayName,
493
+ value: val,
494
+ intensity,
495
+ backgroundColor: bgColor,
496
+ textColor,
497
+ formattedValue: String(val),
498
+ tooltipText: tooltip,
499
+ date: d,
500
+ meta: entry?.meta
501
+ };
502
+ });
503
+ return {
504
+ key: dayName,
505
+ label: dayName,
506
+ cells
507
+ };
508
+ });
509
+ }
510
+ }
511
+ // --- HOUR-BY-HOUR MODE ---
512
+ const hoursList = this.hours();
513
+ const colsList = this.days();
514
+ if (!isSwapped) {
515
+ // Standard: Rows = Hours, Columns = Days
516
+ return hoursList.map((hour) => {
517
+ const hourLabel = this.formatHourLabel(hour, format);
518
+ const cells = colsList.map((col) => {
519
+ const key = `${col}_${hour}`;
520
+ const entry = map.get(key);
521
+ const val = entry?.value ?? 0;
522
+ const { intensity, bgColor, textColor } = getVisuals(val);
523
+ const tooltip = `${col}, ${hourLabel}: ${val}${unitSuffix}`;
524
+ return {
525
+ id: key,
526
+ colKey: col,
527
+ colLabel: col,
528
+ rowKey: hour,
529
+ rowLabel: hourLabel,
530
+ value: val,
531
+ intensity,
532
+ backgroundColor: bgColor,
533
+ textColor,
534
+ formattedValue: String(val),
535
+ tooltipText: tooltip,
536
+ meta: entry?.meta
537
+ };
538
+ });
539
+ return {
540
+ key: hour,
541
+ label: hourLabel,
542
+ cells
543
+ };
544
+ });
545
+ }
546
+ else {
547
+ // Swapped: Rows = Days, Columns = Hours
548
+ return colsList.map((day) => {
549
+ const cells = hoursList.map((hour) => {
550
+ const hourLabel = this.formatHourLabel(hour, format);
551
+ const key = `${day}_${hour}`;
552
+ const entry = map.get(key);
553
+ const val = entry?.value ?? 0;
554
+ const { intensity, bgColor, textColor } = getVisuals(val);
555
+ const tooltip = `${day}, ${hourLabel}: ${val}${unitSuffix}`;
556
+ return {
557
+ id: `${key}_swapped`,
558
+ colKey: hour,
559
+ colLabel: hourLabel,
560
+ rowKey: day,
561
+ rowLabel: day,
562
+ value: val,
563
+ intensity,
564
+ backgroundColor: bgColor,
565
+ textColor,
566
+ formattedValue: String(val),
567
+ tooltipText: tooltip,
568
+ meta: entry?.meta
569
+ };
570
+ });
571
+ return {
572
+ key: day,
573
+ label: day,
574
+ cells
575
+ };
576
+ });
577
+ }
578
+ }, /* @ts-ignore */
579
+ ...(ngDevMode ? [{ debugName: "gridRows" }] : /* istanbul ignore next */ []));
580
+ constructor() {
581
+ // Notify parent on time range boundaries changes
582
+ effect(() => {
583
+ const days = this.days();
584
+ const hours = this.hours();
585
+ const inter = this.interval();
586
+ const dr = this.dateRange();
587
+ const swapped = this.swapAxes();
588
+ this.timeRangeChange.emit({
589
+ interval: inter,
590
+ startHour: hours.length > 0 ? hours[0] : undefined,
591
+ endHour: hours.length > 0 ? hours[hours.length - 1] : undefined,
592
+ days,
593
+ startDate: dr?.startDate ? new Date(dr.startDate) : undefined,
594
+ endDate: dr?.endDate ? new Date(dr.endDate) : undefined,
595
+ dateRange: dr,
596
+ swapAxes: swapped
597
+ });
598
+ });
599
+ // Close dropdowns on outside click
600
+ if (typeof document !== 'undefined') {
601
+ document.addEventListener('click', (event) => {
602
+ const target = event.target;
603
+ if (!this.elementRef.nativeElement.contains(target)) {
604
+ this.isMetricDropdownOpen.set(false);
605
+ this.isExportDropdownOpen.set(false);
606
+ }
607
+ });
608
+ }
609
+ }
610
+ formatHourLabel(hour, format) {
611
+ if (format === '24h') {
612
+ return `${hour.toString().padStart(2, '0')}:00`;
613
+ }
614
+ if (hour === 0)
615
+ return '12 AM';
616
+ if (hour < 12)
617
+ return `${hour} AM`;
618
+ if (hour === 12)
619
+ return '12 PM';
620
+ return `${hour - 12} PM`;
621
+ }
622
+ setInterval(newInterval) {
623
+ this.interval.set(newInterval);
624
+ }
625
+ toggleSwapAxes() {
626
+ this.swapAxes.update((v) => !v);
627
+ }
628
+ onDateRangePickerChange(val) {
629
+ this.dateRange.set(val);
630
+ }
631
+ toggleExpand() {
632
+ this.isExpanded.update((v) => !v);
633
+ }
634
+ toggleMetricDropdown(event) {
635
+ event.stopPropagation();
636
+ this.isMetricDropdownOpen.update((v) => !v);
637
+ this.isExportDropdownOpen.set(false);
638
+ }
639
+ toggleExportDropdown(event) {
640
+ event.stopPropagation();
641
+ this.isExportDropdownOpen.update((v) => !v);
642
+ this.isMetricDropdownOpen.set(false);
643
+ }
644
+ selectMetric(metric) {
645
+ this.selectedMetricId.set(metric.id);
646
+ this.isMetricDropdownOpen.set(false);
647
+ this.metricChange.emit(metric);
648
+ }
649
+ onRefreshClick() {
650
+ this.refresh.emit();
651
+ }
652
+ onCellMouseEnter(cell) {
653
+ this.hoveredCell.set(cell);
654
+ this.cellHover.emit(cell);
655
+ }
656
+ onCellMouseLeave() {
657
+ this.hoveredCell.set(null);
658
+ this.cellHover.emit(null);
659
+ }
660
+ onCellClick(cell, event) {
661
+ this.cellClick.emit({
662
+ cell,
663
+ colKey: cell.colKey,
664
+ rowKey: cell.rowKey,
665
+ value: cell.value,
666
+ interval: this.interval(),
667
+ event
668
+ });
669
+ }
670
+ onKeydown(event, colIdx, rowIdx) {
671
+ const rows = this.gridRows();
672
+ const cols = this.columnHeaders();
673
+ let targetRow = rowIdx;
674
+ let targetCol = colIdx;
675
+ if (event.key === 'ArrowUp') {
676
+ targetRow = Math.max(0, rowIdx - 1);
677
+ event.preventDefault();
678
+ }
679
+ else if (event.key === 'ArrowDown') {
680
+ targetRow = Math.min(rows.length - 1, rowIdx + 1);
681
+ event.preventDefault();
682
+ }
683
+ else if (event.key === 'ArrowLeft') {
684
+ targetCol = Math.max(0, colIdx - 1);
685
+ event.preventDefault();
686
+ }
687
+ else if (event.key === 'ArrowRight') {
688
+ targetCol = Math.min(cols.length - 1, colIdx + 1);
689
+ event.preventDefault();
690
+ }
691
+ else if (event.key === 'Enter' || event.key === ' ') {
692
+ const cell = rows[rowIdx]?.cells[colIdx];
693
+ if (cell) {
694
+ this.cellClick.emit({
695
+ cell,
696
+ colKey: cell.colKey,
697
+ rowKey: cell.rowKey,
698
+ value: cell.value,
699
+ interval: this.interval(),
700
+ event
701
+ });
702
+ }
703
+ event.preventDefault();
704
+ return;
705
+ }
706
+ if (targetRow !== rowIdx || targetCol !== colIdx) {
707
+ this.focusedCoord.set({ colIndex: targetCol, rowIndex: targetRow });
708
+ const cellEl = this.elementRef.nativeElement.querySelector(`[data-cell-coord="${targetRow}_${targetCol}"]`);
709
+ cellEl?.focus();
710
+ }
711
+ }
712
+ triggerExport(format) {
713
+ this.isExportDropdownOpen.set(false);
714
+ const rows = this.gridRows();
715
+ const cols = this.days();
716
+ if (format === 'csv') {
717
+ const header = ['Period', ...cols].join(',');
718
+ const body = rows.map((r) => [r.label, ...r.cells.map((c) => c.value)].join(',')).join('\n');
719
+ const csvContent = `${header}\n${body}`;
720
+ this.downloadFile(csvContent, 'text/csv;charset=utf-8;', `heatmap_${this.title().toLowerCase().replace(/\s+/g, '_')}.csv`);
721
+ this.export.emit({ format: 'csv', data: csvContent });
722
+ }
723
+ else if (format === 'json') {
724
+ const jsonRecords = {};
725
+ rows.forEach((r) => {
726
+ jsonRecords[r.label] = {};
727
+ r.cells.forEach((c) => {
728
+ jsonRecords[r.label][c.colKey] = c.value;
729
+ });
730
+ });
731
+ const jsonStr = JSON.stringify(jsonRecords, null, 2);
732
+ this.downloadFile(jsonStr, 'application/json;charset=utf-8;', `heatmap_${this.title().toLowerCase().replace(/\s+/g, '_')}.json`);
733
+ this.export.emit({ format: 'json', data: jsonRecords });
734
+ }
735
+ }
736
+ downloadFile(content, mimeType, filename) {
737
+ if (typeof window === 'undefined')
738
+ return;
739
+ const blob = new Blob([content], { type: mimeType });
740
+ const url = URL.createObjectURL(blob);
741
+ const a = document.createElement('a');
742
+ a.href = url;
743
+ a.download = filename;
744
+ document.body.appendChild(a);
745
+ a.click();
746
+ document.body.removeChild(a);
747
+ URL.revokeObjectURL(url);
748
+ }
749
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
750
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: TalosHeatmapComponent, isStandalone: true, selector: "talos-heatmap", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, metrics: { classPropertyName: "metrics", publicName: "metrics", isSignal: true, isRequired: false, transformFunction: null }, selectedMetricId: { classPropertyName: "selectedMetricId", publicName: "selectedMetricId", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, dateRange: { classPropertyName: "dateRange", publicName: "dateRange", isSignal: true, isRequired: false, transformFunction: null }, swapAxes: { classPropertyName: "swapAxes", publicName: "swapAxes", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, hoursRange: { classPropertyName: "hoursRange", publicName: "hoursRange", isSignal: true, isRequired: false, transformFunction: null }, timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, days: { classPropertyName: "days", publicName: "days", isSignal: true, isRequired: false, transformFunction: null }, colorScheme: { classPropertyName: "colorScheme", publicName: "colorScheme", isSignal: true, isRequired: false, transformFunction: null }, customColorStops: { classPropertyName: "customColorStops", publicName: "customColorStops", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, cellShape: { classPropertyName: "cellShape", publicName: "cellShape", isSignal: true, isRequired: false, transformFunction: null }, cellSize: { classPropertyName: "cellSize", publicName: "cellSize", isSignal: true, isRequired: false, transformFunction: null }, fitWidth: { classPropertyName: "fitWidth", publicName: "fitWidth", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showRefresh: { classPropertyName: "showRefresh", publicName: "showRefresh", isSignal: true, isRequired: false, transformFunction: null }, showExport: { classPropertyName: "showExport", publicName: "showExport", isSignal: true, isRequired: false, transformFunction: null }, showExpand: { classPropertyName: "showExpand", publicName: "showExpand", isSignal: true, isRequired: false, transformFunction: null }, showSwapAxes: { classPropertyName: "showSwapAxes", publicName: "showSwapAxes", isSignal: true, isRequired: false, transformFunction: null }, showIntervalToggle: { classPropertyName: "showIntervalToggle", publicName: "showIntervalToggle", isSignal: true, isRequired: false, transformFunction: null }, showDateRangePicker: { classPropertyName: "showDateRangePicker", publicName: "showDateRangePicker", isSignal: true, isRequired: false, transformFunction: null }, dateRangePresets: { classPropertyName: "dateRangePresets", publicName: "dateRangePresets", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedMetricId: "selectedMetricIdChange", interval: "intervalChange", dateRange: "dateRangeChange", swapAxes: "swapAxesChange", cellClick: "cellClick", cellHover: "cellHover", timeRangeChange: "timeRangeChange", refresh: "refresh", metricChange: "metricChange", export: "export" }, host: { properties: { "class.talos-heatmap-expanded": "isExpanded()", "class.talos-heatmap-loading": "loading()", "class.talos-heatmap-sm": "cellSize() === \"sm\"", "class.talos-heatmap-md": "cellSize() === \"md\"", "class.talos-heatmap-lg": "cellSize() === \"lg\"", "class.talos-heatmap-pill": "cellShape() === \"pill\"", "class.talos-heatmap-rounded": "cellShape() === \"rounded\"", "class.talos-heatmap-square": "cellShape() === \"square\"", "class.talos-heatmap-fit-width": "isFitWidth()", "class.talos-heatmap-compact-square": "!isFitWidth()", "class.talos-heatmap-swapped-axes": "swapAxes()", "attr.role": "\"region\"", "attr.aria-label": "title()" }, classAttribute: "talos-heatmap" }, ngImport: i0, template: "<div class=\"talos-heatmap-container\">\n <!-- Header Toolbar -->\n @if (showToolbar()) {\n <div class=\"talos-heatmap-header\">\n <div class=\"talos-heatmap-title-area\">\n <h3 class=\"talos-heatmap-title\">{{ title() }}</h3>\n </div>\n\n <div class=\"talos-heatmap-actions\">\n <!-- Interval Selector Toggle (Hour vs Day) -->\n @if (showIntervalToggle()) {\n <div class=\"talos-heatmap-interval-group\" role=\"radiogroup\" aria-label=\"Time Interval\">\n <button type=\"button\" class=\"talos-heatmap-interval-btn\" [class.is-active]=\"interval() === 'hour'\"\n (click)=\"setInterval('hour')\" role=\"radio\" [attr.aria-checked]=\"interval() === 'hour'\">\n <svg lucideClock [size]=\"13\"></svg>\n <span>Hour</span>\n </button>\n <button type=\"button\" class=\"talos-heatmap-interval-btn\" [class.is-active]=\"interval() === 'day'\"\n (click)=\"setInterval('day')\" role=\"radio\" [attr.aria-checked]=\"interval() === 'day'\">\n <svg lucideCalendar [size]=\"13\"></svg>\n <span>Day</span>\n </button>\n </div>\n }\n\n <!-- Date Range Picker Integration -->\n @if (showDateRangePicker()) {\n <div class=\"talos-heatmap-daterange-box\">\n <talos-date-range-picker size=\"sm\" [ngModel]=\"dateRange()\" (rangeChange)=\"onDateRangePickerChange($event)\"\n [presets]=\"dateRangePresets()\" placeholder=\"Select date range\" />\n </div>\n }\n\n <!-- Metric Dropdown Selector -->\n @if (metrics().length > 0) {\n <div class=\"talos-heatmap-dropdown-wrapper\">\n <button type=\"button\" class=\"talos-heatmap-dropdown-btn\" [class.is-open]=\"isMetricDropdownOpen()\"\n (click)=\"toggleMetricDropdown($event)\" aria-haspopup=\"listbox\" [attr.aria-expanded]=\"isMetricDropdownOpen()\">\n <span class=\"talos-heatmap-dropdown-label\">{{ currentMetric()?.label || 'Select metric' }}</span>\n <svg lucideChevronDown [size]=\"14\" class=\"talos-heatmap-dropdown-icon\"></svg>\n </button>\n\n @if (isMetricDropdownOpen()) {\n <div class=\"talos-heatmap-menu\" role=\"listbox\">\n @for (m of metrics(); track m.id) {\n <button type=\"button\" class=\"talos-heatmap-menu-item\" [class.is-selected]=\"m.id === currentMetric()?.id\"\n (click)=\"selectMetric(m)\" role=\"option\" [attr.aria-selected]=\"m.id === currentMetric()?.id\">\n <span>{{ m.label }}</span>\n @if (m.id === currentMetric()?.id) {\n <svg lucideCheck [size]=\"14\" class=\"talos-heatmap-check-icon\"></svg>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Refresh Button -->\n @if (showRefresh()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" [class.is-spinning]=\"loading()\" (click)=\"onRefreshClick()\"\n title=\"Refresh data\" aria-label=\"Refresh data\">\n <svg lucideRefreshCw [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n }\n\n <!-- Export Dropdown Button -->\n @if (showExport()) {\n <div class=\"talos-heatmap-dropdown-wrapper\">\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" (click)=\"toggleExportDropdown($event)\" title=\"Export data\"\n aria-label=\"Export data\">\n <svg lucideUpload [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n\n @if (isExportDropdownOpen()) {\n <div class=\"talos-heatmap-menu talos-heatmap-export-menu\" role=\"menu\">\n <button type=\"button\" class=\"talos-heatmap-menu-item\" (click)=\"triggerExport('csv')\" role=\"menuitem\">\n <svg lucideFileSpreadsheet [size]=\"14\" class=\"talos-heatmap-menu-icon\"></svg>\n <span>Export to CSV</span>\n </button>\n <button type=\"button\" class=\"talos-heatmap-menu-item\" (click)=\"triggerExport('json')\" role=\"menuitem\">\n <svg lucideFileJson [size]=\"14\" class=\"talos-heatmap-menu-icon\"></svg>\n <span>Export to JSON</span>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Swap Axes Button -->\n @if (showSwapAxes()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" [class.is-active]=\"swapAxes()\" (click)=\"toggleSwapAxes()\"\n [title]=\"swapAxes() ? 'Reset axis orientation' : 'Swap axes (Days / Hours)'\"\n [attr.aria-label]=\"swapAxes() ? 'Reset axis orientation' : 'Swap axes (Days / Hours)'\">\n <svg lucideArrowLeftRight [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n }\n\n <!-- Fullscreen / Expand Button -->\n @if (showExpand()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" (click)=\"toggleExpand()\"\n [title]=\"isExpanded() ? 'Minimize' : 'Expand'\" [aria-label]=\"isExpanded() ? 'Minimize' : 'Expand'\">\n @if (isExpanded()) {\n <svg lucideMinimize2 [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n } @else {\n <svg lucideMaximize2 [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Heatmap Matrix Grid Wrapper -->\n <div class=\"talos-heatmap-body\" [class.is-loading]=\"loading()\">\n <!-- Grid Table -->\n <div class=\"talos-heatmap-grid\" role=\"grid\" [attr.aria-rowcount]=\"gridRows().length + 1\"\n [attr.aria-colcount]=\"columnHeaders().length + 1\">\n <!-- Column Headers -->\n <div class=\"talos-heatmap-row talos-heatmap-header-row\" role=\"row\" aria-rowindex=\"1\">\n <div class=\"talos-heatmap-corner-cell\" role=\"columnheader\"></div>\n @for (col of columnHeaders(); track col.key; let colIdx = $index) {\n <div class=\"talos-heatmap-col-header\" role=\"columnheader\" [attr.aria-colindex]=\"colIdx + 2\">\n {{ col.label }}\n </div>\n }\n </div>\n\n <!-- Data Rows -->\n @for (row of gridRows(); track row.key; let rowIdx = $index) {\n <div class=\"talos-heatmap-row\" role=\"row\" [attr.aria-rowindex]=\"rowIdx + 2\">\n <!-- Row Header (Hour or Week Range) -->\n <div class=\"talos-heatmap-row-header\" role=\"rowheader\" aria-colindex=\"1\" [title]=\"row.label\">\n {{ row.label }}\n </div>\n\n <!-- Heatmap Cells -->\n @for (cell of row.cells; track cell.id; let colIdx = $index) {\n <div class=\"talos-heatmap-cell-wrapper\" role=\"gridcell\" [attr.aria-colindex]=\"colIdx + 2\"\n [attr.aria-label]=\"cell.tooltipText\" tabindex=\"0\" [attr.data-cell-coord]=\"rowIdx + '_' + colIdx\"\n [talosTooltip]=\"cell.tooltipText\" (mouseenter)=\"onCellMouseEnter(cell)\" (mouseleave)=\"onCellMouseLeave()\"\n (click)=\"onCellClick(cell, $event)\" (keydown)=\"onKeydown($event, colIdx, rowIdx)\">\n <div class=\"talos-heatmap-pill\" [style.background-color]=\"cell.backgroundColor\" [style.color]=\"cell.textColor\"\n [class.has-value]=\"cell.value > 0\">\n @if (showValues()) {\n <span class=\"talos-heatmap-cell-value\">{{ cell.formattedValue }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Loading Skeleton Shimmer Overlay -->\n @if (loading()) {\n <div class=\"talos-heatmap-loading-overlay\" aria-hidden=\"true\">\n <div class=\"talos-heatmap-loading-spinner-box\">\n <svg lucideRefreshCw [size]=\"16\" class=\"talos-heatmap-loading-spinner\"></svg>\n <span>Loading data...</span>\n </div>\n </div>\n }\n </div>\n\n <!-- Bottom Legend Bar -->\n @if (showLegend()) {\n <div class=\"talos-heatmap-legend\">\n <span class=\"talos-heatmap-legend-bound\">{{ computedScaleBounds().min }}</span>\n <div class=\"talos-heatmap-legend-bar\" [style.background]=\"legendGradientCss()\" aria-hidden=\"true\"></div>\n <span class=\"talos-heatmap-legend-bound\">{{ computedScaleBounds().max }}</span>\n </div>\n }\n</div>", styles: [":host{display:block;font-family:inherit;--talos-heatmap-bg: var(--talos-card-bg, var(--talos-bg-surface, #ffffff));--talos-heatmap-text: var(--talos-text-color, #0f172a);--talos-heatmap-muted: var(--talos-text-muted, #64748b);--talos-heatmap-border: var(--talos-border-color, #e2e8f0);--talos-heatmap-hover-bg: var(--talos-primary-light, #f1f5f9);--talos-heatmap-cell-height: 28px;--talos-heatmap-cell-radius: 9999px;--talos-heatmap-row-header-width: 68px;--talos-heatmap-cell-font-size: .85rem;--talos-heatmap-gap: 6px;--talos-heatmap-square-size: 32px}:host(.talos-heatmap-sm){--talos-heatmap-cell-height: 22px;--talos-heatmap-row-header-width: 56px;--talos-heatmap-cell-font-size: .72rem;--talos-heatmap-square-size: 24px;--talos-heatmap-gap: 4px}:host(.talos-heatmap-md){--talos-heatmap-cell-height: 28px;--talos-heatmap-row-header-width: 68px;--talos-heatmap-cell-font-size: .82rem;--talos-heatmap-square-size: 32px;--talos-heatmap-gap: 6px}:host(.talos-heatmap-lg){--talos-heatmap-cell-height: 36px;--talos-heatmap-row-header-width: 80px;--talos-heatmap-cell-font-size: .92rem;--talos-heatmap-square-size: 40px;--talos-heatmap-gap: 8px}:host(.talos-heatmap-square){--talos-heatmap-cell-radius: 6px}:host(.talos-heatmap-rounded){--talos-heatmap-cell-radius: 8px}:host(.talos-heatmap-pill){--talos-heatmap-cell-radius: 9999px}:host(.talos-heatmap-expanded){position:fixed;inset:16px;z-index:1000;background:var(--talos-heatmap-bg);box-shadow:0 25px 50px -12px #00000059;border-radius:16px;padding:24px;overflow:auto;border:1px solid var(--talos-heatmap-border)}.talos-heatmap-container{display:flex;flex-direction:column;background:var(--talos-heatmap-bg);border-radius:12px;position:relative;width:100%}.talos-heatmap-header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:20px;flex-wrap:wrap}.talos-heatmap-title{margin:0;font-size:1.15rem;font-weight:700;color:var(--talos-heatmap-text);letter-spacing:-.015em}.talos-heatmap-actions{display:flex;align-items:center;gap:8px;position:relative;flex-wrap:wrap}.talos-heatmap-interval-group{display:inline-flex;align-items:center;padding:2px;background:var(--talos-bg-color, #f1f5f9);border-radius:8px;border:1px solid var(--talos-heatmap-border);gap:2px}.talos-heatmap-interval-btn{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;font-size:.78rem;font-weight:600;color:var(--talos-heatmap-muted);background:transparent;border:none;border-radius:6px;cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-interval-btn:hover{color:var(--talos-heatmap-text)}.talos-heatmap-interval-btn.is-active{background:var(--talos-card-bg, #ffffff);color:var(--talos-primary-color, #4338ca);box-shadow:0 1px 3px #00000014}.talos-heatmap-daterange-box{min-width:220px}.talos-heatmap-dropdown-wrapper{position:relative}.talos-heatmap-dropdown-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:.85rem;font-weight:500;color:var(--talos-heatmap-text);background:var(--talos-bg-color, #f8fafc);border:1px solid var(--talos-heatmap-border);border-radius:8px;cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-dropdown-btn:hover{background:var(--talos-primary-light, #f1f5f9);border-color:var(--talos-border-hover, #cbd5e1)}.talos-heatmap-dropdown-btn.is-open{background:var(--talos-primary-light-hover, #e2e8f0);border-color:var(--talos-border-hover, #94a3b8)}.talos-heatmap-dropdown-btn .talos-heatmap-dropdown-icon{width:14px;height:14px;color:var(--talos-heatmap-muted)}.talos-heatmap-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:8px;border:1px solid transparent;background:transparent;color:var(--talos-heatmap-muted);cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-icon-btn:hover{background:var(--talos-heatmap-hover-bg);color:var(--talos-heatmap-text)}.talos-heatmap-icon-btn.is-active{background:var(--talos-primary-light, #e0e7ff);color:var(--talos-primary-color, #4338ca);border-color:var(--talos-border-color, #c7d2fe)}.talos-heatmap-icon-btn:active{transform:scale(.95)}.talos-heatmap-icon-btn.is-spinning .talos-heatmap-action-icon{animation:talos-heatmap-spin .8s linear infinite}.talos-heatmap-icon-btn .talos-heatmap-action-icon{width:16px;height:16px}@keyframes talos-heatmap-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.talos-heatmap-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:50;min-width:170px;background:var(--talos-dropdown-bg, var(--talos-card-bg, #ffffff));border:1px solid var(--talos-dropdown-border, var(--talos-heatmap-border));border-radius:10px;box-shadow:var(--talos-dropdown-shadow, 0 10px 25px -5px rgba(0, 0, 0, .12), 0 8px 10px -6px rgba(0, 0, 0, .08));padding:4px;display:flex;flex-direction:column;gap:2px;animation:talos-heatmap-menu-fade .15s cubic-bezier(.16,1,.3,1)}@keyframes talos-heatmap-menu-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.talos-heatmap-menu-item{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:7px 10px;font-size:.82rem;font-weight:500;color:var(--talos-heatmap-text);background:transparent;border:none;border-radius:6px;text-align:left;cursor:pointer;transition:background .12s ease}.talos-heatmap-menu-item:hover{background:var(--talos-dropdown-hover-bg, #f1f5f9)}.talos-heatmap-menu-item.is-selected{font-weight:600;color:var(--talos-primary-color, #4338ca)}.talos-heatmap-menu-item .talos-heatmap-check-icon{width:14px;height:14px;color:var(--talos-primary-color, #4338ca)}.talos-heatmap-menu-item .talos-heatmap-menu-icon{width:14px;height:14px;color:var(--talos-heatmap-muted)}.talos-heatmap-body{position:relative;width:100%;overflow-x:auto;padding-bottom:8px}.talos-heatmap-body.is-loading{pointer-events:none;-webkit-user-select:none;user-select:none}.talos-heatmap-grid{display:flex;flex-direction:column;gap:var(--talos-heatmap-gap);width:100%}.talos-heatmap-row{display:flex;align-items:center;gap:var(--talos-heatmap-gap);width:100%}.talos-heatmap-header-row{margin-bottom:2px}.talos-heatmap-corner-cell{width:var(--talos-heatmap-row-header-width);flex-shrink:0}.talos-heatmap-row-header{width:var(--talos-heatmap-row-header-width);flex-shrink:0;text-align:right;padding-right:12px;font-size:.82rem;font-weight:500;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}:host(.talos-heatmap-fit-width) .talos-heatmap-grid{min-width:440px;width:100%}:host(.talos-heatmap-fit-width) .talos-heatmap-col-header{flex:1;text-align:center;font-size:.82rem;font-weight:600;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;letter-spacing:.01em}:host(.talos-heatmap-fit-width) .talos-heatmap-cell-wrapper{flex:1;height:var(--talos-heatmap-cell-height);position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;outline:none;border-radius:var(--talos-heatmap-cell-radius);transition:transform .15s ease}:host(.talos-heatmap-fit-width) .talos-heatmap-cell-wrapper:focus-visible{box-shadow:0 0 0 2px #4338ca,0 0 0 4px #4338ca40;z-index:5}:host(.talos-heatmap-compact-square) .talos-heatmap-grid{min-width:auto;width:max-content}:host(.talos-heatmap-compact-square) .talos-heatmap-col-header{width:var(--talos-heatmap-square-size);flex:0 0 var(--talos-heatmap-square-size);text-align:center;font-size:.78rem;font-weight:600;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;letter-spacing:.01em}:host(.talos-heatmap-compact-square) .talos-heatmap-cell-wrapper{width:var(--talos-heatmap-square-size);height:var(--talos-heatmap-square-size);flex:0 0 var(--talos-heatmap-square-size);aspect-ratio:1/1;position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;outline:none;border-radius:var(--talos-heatmap-cell-radius);transition:transform .15s ease}:host(.talos-heatmap-compact-square) .talos-heatmap-cell-wrapper:focus-visible{box-shadow:0 0 0 2px #4338ca,0 0 0 4px #4338ca40;z-index:5}.talos-heatmap-pill{width:100%;height:100%;display:flex;align-items:center;justify-content:center;border-radius:var(--talos-heatmap-cell-radius);font-size:var(--talos-heatmap-cell-font-size);font-weight:600;line-height:1;-webkit-user-select:none;user-select:none;box-shadow:inset 0 0 0 1px #0000000a;transition:transform .15s cubic-bezier(.16,1,.3,1),box-shadow .15s ease,filter .15s ease}.talos-heatmap-pill:not(.has-value){box-shadow:inset 0 0 0 1px #e2e8f0e6}.talos-heatmap-cell-wrapper:hover .talos-heatmap-pill{transform:translateY(-2px) scale(1.05);box-shadow:0 6px 14px -2px #00000024,0 2px 4px -1px #0000000f;filter:brightness(1.03);z-index:2}.talos-heatmap-cell-wrapper:active .talos-heatmap-pill{transform:translateY(0) scale(.96)}.talos-heatmap-cell-value{display:inline-block;text-align:center}.talos-heatmap-loading-overlay{position:absolute;inset:0;background:var(--talos-loading-overlay-bg, rgba(255, 255, 255, .75));-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:40;border-radius:8px;animation:talos-heatmap-fade-in .2s ease}@keyframes talos-heatmap-fade-in{0%{opacity:0}to{opacity:1}}.talos-heatmap-loading-spinner-box{display:flex;align-items:center;gap:8px;padding:8px 16px;background:var(--talos-card-bg, #ffffff);border:1px solid var(--talos-heatmap-border);border-radius:8px;box-shadow:0 4px 12px #00000014;font-size:.85rem;font-weight:500;color:var(--talos-heatmap-text)}.talos-heatmap-loading-spinner-box .talos-heatmap-loading-spinner{width:16px;height:16px;color:var(--talos-primary-color, #4338ca);animation:talos-heatmap-spin .8s linear infinite}.talos-heatmap-legend{display:flex;align-items:center;gap:12px;margin-top:18px;padding-left:var(--talos-heatmap-row-header-width)}.talos-heatmap-legend-bound{font-size:.82rem;font-weight:600;color:var(--talos-heatmap-muted);min-width:12px}.talos-heatmap-legend-bar{height:8px;width:130px;border-radius:9999px;box-shadow:inset 0 1px 2px #00000014}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: DateRangePickerComponent, selector: "talos-date-range-picker", inputs: ["placeholder", "label", "floatingLabel", "floating", "required", "disabled", "clearable", "size", "displayFormat", "valueFormat", "showTime", "use24Hour", "showSeconds", "minuteStep", "minDate", "maxDate", "minSpan", "maxSpan", "firstDayOfWeek", "presets", "presetType", "filterDate"], outputs: ["rangeChange", "opened", "closed"] }, { kind: "directive", type: TalosTooltipDirective, selector: "[talosTooltip], [tooltip]", inputs: ["talosTooltip", "tooltip", "tooltipPosition", "tooltipDisabled"] }, { kind: "component", type: LucideRefreshCw, selector: "svg[lucideRefreshCw]" }, { kind: "component", type: LucideUpload, selector: "svg[lucideUpload]" }, { kind: "component", type: LucideMaximize2, selector: "svg[lucideMaximize2]" }, { kind: "component", type: LucideMinimize2, selector: "svg[lucideMinimize2]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: LucideCheck, selector: "svg[lucideCheck]" }, { kind: "component", type: LucideFileSpreadsheet, selector: "svg[lucideFileSpreadsheet]" }, { kind: "component", type: LucideFileJson, selector: "svg[lucideFileBraces], svg[lucideFileJson]" }, { kind: "component", type: LucideCalendar, selector: "svg[lucideCalendar]" }, { kind: "component", type: LucideClock, selector: "svg[lucideClock]" }, { kind: "component", type: LucideArrowLeftRight, selector: "svg[lucideArrowLeftRight]" }] });
751
+ }
752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapComponent, decorators: [{
753
+ type: Component,
754
+ args: [{ selector: 'talos-heatmap', imports: [
755
+ FormsModule,
756
+ DateRangePickerComponent,
757
+ TalosTooltipDirective,
758
+ LucideRefreshCw,
759
+ LucideUpload,
760
+ LucideMaximize2,
761
+ LucideMinimize2,
762
+ LucideChevronDown,
763
+ LucideCheck,
764
+ LucideFileSpreadsheet,
765
+ LucideFileJson,
766
+ LucideCalendar,
767
+ LucideClock,
768
+ LucideArrowLeftRight
769
+ ], host: {
770
+ 'class': 'talos-heatmap',
771
+ '[class.talos-heatmap-expanded]': 'isExpanded()',
772
+ '[class.talos-heatmap-loading]': 'loading()',
773
+ '[class.talos-heatmap-sm]': 'cellSize() === "sm"',
774
+ '[class.talos-heatmap-md]': 'cellSize() === "md"',
775
+ '[class.talos-heatmap-lg]': 'cellSize() === "lg"',
776
+ '[class.talos-heatmap-pill]': 'cellShape() === "pill"',
777
+ '[class.talos-heatmap-rounded]': 'cellShape() === "rounded"',
778
+ '[class.talos-heatmap-square]': 'cellShape() === "square"',
779
+ '[class.talos-heatmap-fit-width]': 'isFitWidth()',
780
+ '[class.talos-heatmap-compact-square]': '!isFitWidth()',
781
+ '[class.talos-heatmap-swapped-axes]': 'swapAxes()',
782
+ '[attr.role]': '"region"',
783
+ '[attr.aria-label]': 'title()'
784
+ }, template: "<div class=\"talos-heatmap-container\">\n <!-- Header Toolbar -->\n @if (showToolbar()) {\n <div class=\"talos-heatmap-header\">\n <div class=\"talos-heatmap-title-area\">\n <h3 class=\"talos-heatmap-title\">{{ title() }}</h3>\n </div>\n\n <div class=\"talos-heatmap-actions\">\n <!-- Interval Selector Toggle (Hour vs Day) -->\n @if (showIntervalToggle()) {\n <div class=\"talos-heatmap-interval-group\" role=\"radiogroup\" aria-label=\"Time Interval\">\n <button type=\"button\" class=\"talos-heatmap-interval-btn\" [class.is-active]=\"interval() === 'hour'\"\n (click)=\"setInterval('hour')\" role=\"radio\" [attr.aria-checked]=\"interval() === 'hour'\">\n <svg lucideClock [size]=\"13\"></svg>\n <span>Hour</span>\n </button>\n <button type=\"button\" class=\"talos-heatmap-interval-btn\" [class.is-active]=\"interval() === 'day'\"\n (click)=\"setInterval('day')\" role=\"radio\" [attr.aria-checked]=\"interval() === 'day'\">\n <svg lucideCalendar [size]=\"13\"></svg>\n <span>Day</span>\n </button>\n </div>\n }\n\n <!-- Date Range Picker Integration -->\n @if (showDateRangePicker()) {\n <div class=\"talos-heatmap-daterange-box\">\n <talos-date-range-picker size=\"sm\" [ngModel]=\"dateRange()\" (rangeChange)=\"onDateRangePickerChange($event)\"\n [presets]=\"dateRangePresets()\" placeholder=\"Select date range\" />\n </div>\n }\n\n <!-- Metric Dropdown Selector -->\n @if (metrics().length > 0) {\n <div class=\"talos-heatmap-dropdown-wrapper\">\n <button type=\"button\" class=\"talos-heatmap-dropdown-btn\" [class.is-open]=\"isMetricDropdownOpen()\"\n (click)=\"toggleMetricDropdown($event)\" aria-haspopup=\"listbox\" [attr.aria-expanded]=\"isMetricDropdownOpen()\">\n <span class=\"talos-heatmap-dropdown-label\">{{ currentMetric()?.label || 'Select metric' }}</span>\n <svg lucideChevronDown [size]=\"14\" class=\"talos-heatmap-dropdown-icon\"></svg>\n </button>\n\n @if (isMetricDropdownOpen()) {\n <div class=\"talos-heatmap-menu\" role=\"listbox\">\n @for (m of metrics(); track m.id) {\n <button type=\"button\" class=\"talos-heatmap-menu-item\" [class.is-selected]=\"m.id === currentMetric()?.id\"\n (click)=\"selectMetric(m)\" role=\"option\" [attr.aria-selected]=\"m.id === currentMetric()?.id\">\n <span>{{ m.label }}</span>\n @if (m.id === currentMetric()?.id) {\n <svg lucideCheck [size]=\"14\" class=\"talos-heatmap-check-icon\"></svg>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Refresh Button -->\n @if (showRefresh()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" [class.is-spinning]=\"loading()\" (click)=\"onRefreshClick()\"\n title=\"Refresh data\" aria-label=\"Refresh data\">\n <svg lucideRefreshCw [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n }\n\n <!-- Export Dropdown Button -->\n @if (showExport()) {\n <div class=\"talos-heatmap-dropdown-wrapper\">\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" (click)=\"toggleExportDropdown($event)\" title=\"Export data\"\n aria-label=\"Export data\">\n <svg lucideUpload [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n\n @if (isExportDropdownOpen()) {\n <div class=\"talos-heatmap-menu talos-heatmap-export-menu\" role=\"menu\">\n <button type=\"button\" class=\"talos-heatmap-menu-item\" (click)=\"triggerExport('csv')\" role=\"menuitem\">\n <svg lucideFileSpreadsheet [size]=\"14\" class=\"talos-heatmap-menu-icon\"></svg>\n <span>Export to CSV</span>\n </button>\n <button type=\"button\" class=\"talos-heatmap-menu-item\" (click)=\"triggerExport('json')\" role=\"menuitem\">\n <svg lucideFileJson [size]=\"14\" class=\"talos-heatmap-menu-icon\"></svg>\n <span>Export to JSON</span>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Swap Axes Button -->\n @if (showSwapAxes()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" [class.is-active]=\"swapAxes()\" (click)=\"toggleSwapAxes()\"\n [title]=\"swapAxes() ? 'Reset axis orientation' : 'Swap axes (Days / Hours)'\"\n [attr.aria-label]=\"swapAxes() ? 'Reset axis orientation' : 'Swap axes (Days / Hours)'\">\n <svg lucideArrowLeftRight [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n </button>\n }\n\n <!-- Fullscreen / Expand Button -->\n @if (showExpand()) {\n <button type=\"button\" class=\"talos-heatmap-icon-btn\" (click)=\"toggleExpand()\"\n [title]=\"isExpanded() ? 'Minimize' : 'Expand'\" [aria-label]=\"isExpanded() ? 'Minimize' : 'Expand'\">\n @if (isExpanded()) {\n <svg lucideMinimize2 [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n } @else {\n <svg lucideMaximize2 [size]=\"16\" class=\"talos-heatmap-action-icon\"></svg>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Heatmap Matrix Grid Wrapper -->\n <div class=\"talos-heatmap-body\" [class.is-loading]=\"loading()\">\n <!-- Grid Table -->\n <div class=\"talos-heatmap-grid\" role=\"grid\" [attr.aria-rowcount]=\"gridRows().length + 1\"\n [attr.aria-colcount]=\"columnHeaders().length + 1\">\n <!-- Column Headers -->\n <div class=\"talos-heatmap-row talos-heatmap-header-row\" role=\"row\" aria-rowindex=\"1\">\n <div class=\"talos-heatmap-corner-cell\" role=\"columnheader\"></div>\n @for (col of columnHeaders(); track col.key; let colIdx = $index) {\n <div class=\"talos-heatmap-col-header\" role=\"columnheader\" [attr.aria-colindex]=\"colIdx + 2\">\n {{ col.label }}\n </div>\n }\n </div>\n\n <!-- Data Rows -->\n @for (row of gridRows(); track row.key; let rowIdx = $index) {\n <div class=\"talos-heatmap-row\" role=\"row\" [attr.aria-rowindex]=\"rowIdx + 2\">\n <!-- Row Header (Hour or Week Range) -->\n <div class=\"talos-heatmap-row-header\" role=\"rowheader\" aria-colindex=\"1\" [title]=\"row.label\">\n {{ row.label }}\n </div>\n\n <!-- Heatmap Cells -->\n @for (cell of row.cells; track cell.id; let colIdx = $index) {\n <div class=\"talos-heatmap-cell-wrapper\" role=\"gridcell\" [attr.aria-colindex]=\"colIdx + 2\"\n [attr.aria-label]=\"cell.tooltipText\" tabindex=\"0\" [attr.data-cell-coord]=\"rowIdx + '_' + colIdx\"\n [talosTooltip]=\"cell.tooltipText\" (mouseenter)=\"onCellMouseEnter(cell)\" (mouseleave)=\"onCellMouseLeave()\"\n (click)=\"onCellClick(cell, $event)\" (keydown)=\"onKeydown($event, colIdx, rowIdx)\">\n <div class=\"talos-heatmap-pill\" [style.background-color]=\"cell.backgroundColor\" [style.color]=\"cell.textColor\"\n [class.has-value]=\"cell.value > 0\">\n @if (showValues()) {\n <span class=\"talos-heatmap-cell-value\">{{ cell.formattedValue }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Loading Skeleton Shimmer Overlay -->\n @if (loading()) {\n <div class=\"talos-heatmap-loading-overlay\" aria-hidden=\"true\">\n <div class=\"talos-heatmap-loading-spinner-box\">\n <svg lucideRefreshCw [size]=\"16\" class=\"talos-heatmap-loading-spinner\"></svg>\n <span>Loading data...</span>\n </div>\n </div>\n }\n </div>\n\n <!-- Bottom Legend Bar -->\n @if (showLegend()) {\n <div class=\"talos-heatmap-legend\">\n <span class=\"talos-heatmap-legend-bound\">{{ computedScaleBounds().min }}</span>\n <div class=\"talos-heatmap-legend-bar\" [style.background]=\"legendGradientCss()\" aria-hidden=\"true\"></div>\n <span class=\"talos-heatmap-legend-bound\">{{ computedScaleBounds().max }}</span>\n </div>\n }\n</div>", styles: [":host{display:block;font-family:inherit;--talos-heatmap-bg: var(--talos-card-bg, var(--talos-bg-surface, #ffffff));--talos-heatmap-text: var(--talos-text-color, #0f172a);--talos-heatmap-muted: var(--talos-text-muted, #64748b);--talos-heatmap-border: var(--talos-border-color, #e2e8f0);--talos-heatmap-hover-bg: var(--talos-primary-light, #f1f5f9);--talos-heatmap-cell-height: 28px;--talos-heatmap-cell-radius: 9999px;--talos-heatmap-row-header-width: 68px;--talos-heatmap-cell-font-size: .85rem;--talos-heatmap-gap: 6px;--talos-heatmap-square-size: 32px}:host(.talos-heatmap-sm){--talos-heatmap-cell-height: 22px;--talos-heatmap-row-header-width: 56px;--talos-heatmap-cell-font-size: .72rem;--talos-heatmap-square-size: 24px;--talos-heatmap-gap: 4px}:host(.talos-heatmap-md){--talos-heatmap-cell-height: 28px;--talos-heatmap-row-header-width: 68px;--talos-heatmap-cell-font-size: .82rem;--talos-heatmap-square-size: 32px;--talos-heatmap-gap: 6px}:host(.talos-heatmap-lg){--talos-heatmap-cell-height: 36px;--talos-heatmap-row-header-width: 80px;--talos-heatmap-cell-font-size: .92rem;--talos-heatmap-square-size: 40px;--talos-heatmap-gap: 8px}:host(.talos-heatmap-square){--talos-heatmap-cell-radius: 6px}:host(.talos-heatmap-rounded){--talos-heatmap-cell-radius: 8px}:host(.talos-heatmap-pill){--talos-heatmap-cell-radius: 9999px}:host(.talos-heatmap-expanded){position:fixed;inset:16px;z-index:1000;background:var(--talos-heatmap-bg);box-shadow:0 25px 50px -12px #00000059;border-radius:16px;padding:24px;overflow:auto;border:1px solid var(--talos-heatmap-border)}.talos-heatmap-container{display:flex;flex-direction:column;background:var(--talos-heatmap-bg);border-radius:12px;position:relative;width:100%}.talos-heatmap-header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:20px;flex-wrap:wrap}.talos-heatmap-title{margin:0;font-size:1.15rem;font-weight:700;color:var(--talos-heatmap-text);letter-spacing:-.015em}.talos-heatmap-actions{display:flex;align-items:center;gap:8px;position:relative;flex-wrap:wrap}.talos-heatmap-interval-group{display:inline-flex;align-items:center;padding:2px;background:var(--talos-bg-color, #f1f5f9);border-radius:8px;border:1px solid var(--talos-heatmap-border);gap:2px}.talos-heatmap-interval-btn{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;font-size:.78rem;font-weight:600;color:var(--talos-heatmap-muted);background:transparent;border:none;border-radius:6px;cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-interval-btn:hover{color:var(--talos-heatmap-text)}.talos-heatmap-interval-btn.is-active{background:var(--talos-card-bg, #ffffff);color:var(--talos-primary-color, #4338ca);box-shadow:0 1px 3px #00000014}.talos-heatmap-daterange-box{min-width:220px}.talos-heatmap-dropdown-wrapper{position:relative}.talos-heatmap-dropdown-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:.85rem;font-weight:500;color:var(--talos-heatmap-text);background:var(--talos-bg-color, #f8fafc);border:1px solid var(--talos-heatmap-border);border-radius:8px;cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-dropdown-btn:hover{background:var(--talos-primary-light, #f1f5f9);border-color:var(--talos-border-hover, #cbd5e1)}.talos-heatmap-dropdown-btn.is-open{background:var(--talos-primary-light-hover, #e2e8f0);border-color:var(--talos-border-hover, #94a3b8)}.talos-heatmap-dropdown-btn .talos-heatmap-dropdown-icon{width:14px;height:14px;color:var(--talos-heatmap-muted)}.talos-heatmap-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:8px;border:1px solid transparent;background:transparent;color:var(--talos-heatmap-muted);cursor:pointer;outline:none;transition:all .15s ease}.talos-heatmap-icon-btn:hover{background:var(--talos-heatmap-hover-bg);color:var(--talos-heatmap-text)}.talos-heatmap-icon-btn.is-active{background:var(--talos-primary-light, #e0e7ff);color:var(--talos-primary-color, #4338ca);border-color:var(--talos-border-color, #c7d2fe)}.talos-heatmap-icon-btn:active{transform:scale(.95)}.talos-heatmap-icon-btn.is-spinning .talos-heatmap-action-icon{animation:talos-heatmap-spin .8s linear infinite}.talos-heatmap-icon-btn .talos-heatmap-action-icon{width:16px;height:16px}@keyframes talos-heatmap-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.talos-heatmap-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:50;min-width:170px;background:var(--talos-dropdown-bg, var(--talos-card-bg, #ffffff));border:1px solid var(--talos-dropdown-border, var(--talos-heatmap-border));border-radius:10px;box-shadow:var(--talos-dropdown-shadow, 0 10px 25px -5px rgba(0, 0, 0, .12), 0 8px 10px -6px rgba(0, 0, 0, .08));padding:4px;display:flex;flex-direction:column;gap:2px;animation:talos-heatmap-menu-fade .15s cubic-bezier(.16,1,.3,1)}@keyframes talos-heatmap-menu-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.talos-heatmap-menu-item{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:7px 10px;font-size:.82rem;font-weight:500;color:var(--talos-heatmap-text);background:transparent;border:none;border-radius:6px;text-align:left;cursor:pointer;transition:background .12s ease}.talos-heatmap-menu-item:hover{background:var(--talos-dropdown-hover-bg, #f1f5f9)}.talos-heatmap-menu-item.is-selected{font-weight:600;color:var(--talos-primary-color, #4338ca)}.talos-heatmap-menu-item .talos-heatmap-check-icon{width:14px;height:14px;color:var(--talos-primary-color, #4338ca)}.talos-heatmap-menu-item .talos-heatmap-menu-icon{width:14px;height:14px;color:var(--talos-heatmap-muted)}.talos-heatmap-body{position:relative;width:100%;overflow-x:auto;padding-bottom:8px}.talos-heatmap-body.is-loading{pointer-events:none;-webkit-user-select:none;user-select:none}.talos-heatmap-grid{display:flex;flex-direction:column;gap:var(--talos-heatmap-gap);width:100%}.talos-heatmap-row{display:flex;align-items:center;gap:var(--talos-heatmap-gap);width:100%}.talos-heatmap-header-row{margin-bottom:2px}.talos-heatmap-corner-cell{width:var(--talos-heatmap-row-header-width);flex-shrink:0}.talos-heatmap-row-header{width:var(--talos-heatmap-row-header-width);flex-shrink:0;text-align:right;padding-right:12px;font-size:.82rem;font-weight:500;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}:host(.talos-heatmap-fit-width) .talos-heatmap-grid{min-width:440px;width:100%}:host(.talos-heatmap-fit-width) .talos-heatmap-col-header{flex:1;text-align:center;font-size:.82rem;font-weight:600;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;letter-spacing:.01em}:host(.talos-heatmap-fit-width) .talos-heatmap-cell-wrapper{flex:1;height:var(--talos-heatmap-cell-height);position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;outline:none;border-radius:var(--talos-heatmap-cell-radius);transition:transform .15s ease}:host(.talos-heatmap-fit-width) .talos-heatmap-cell-wrapper:focus-visible{box-shadow:0 0 0 2px #4338ca,0 0 0 4px #4338ca40;z-index:5}:host(.talos-heatmap-compact-square) .talos-heatmap-grid{min-width:auto;width:max-content}:host(.talos-heatmap-compact-square) .talos-heatmap-col-header{width:var(--talos-heatmap-square-size);flex:0 0 var(--talos-heatmap-square-size);text-align:center;font-size:.78rem;font-weight:600;color:var(--talos-heatmap-muted);-webkit-user-select:none;user-select:none;letter-spacing:.01em}:host(.talos-heatmap-compact-square) .talos-heatmap-cell-wrapper{width:var(--talos-heatmap-square-size);height:var(--talos-heatmap-square-size);flex:0 0 var(--talos-heatmap-square-size);aspect-ratio:1/1;position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;outline:none;border-radius:var(--talos-heatmap-cell-radius);transition:transform .15s ease}:host(.talos-heatmap-compact-square) .talos-heatmap-cell-wrapper:focus-visible{box-shadow:0 0 0 2px #4338ca,0 0 0 4px #4338ca40;z-index:5}.talos-heatmap-pill{width:100%;height:100%;display:flex;align-items:center;justify-content:center;border-radius:var(--talos-heatmap-cell-radius);font-size:var(--talos-heatmap-cell-font-size);font-weight:600;line-height:1;-webkit-user-select:none;user-select:none;box-shadow:inset 0 0 0 1px #0000000a;transition:transform .15s cubic-bezier(.16,1,.3,1),box-shadow .15s ease,filter .15s ease}.talos-heatmap-pill:not(.has-value){box-shadow:inset 0 0 0 1px #e2e8f0e6}.talos-heatmap-cell-wrapper:hover .talos-heatmap-pill{transform:translateY(-2px) scale(1.05);box-shadow:0 6px 14px -2px #00000024,0 2px 4px -1px #0000000f;filter:brightness(1.03);z-index:2}.talos-heatmap-cell-wrapper:active .talos-heatmap-pill{transform:translateY(0) scale(.96)}.talos-heatmap-cell-value{display:inline-block;text-align:center}.talos-heatmap-loading-overlay{position:absolute;inset:0;background:var(--talos-loading-overlay-bg, rgba(255, 255, 255, .75));-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:40;border-radius:8px;animation:talos-heatmap-fade-in .2s ease}@keyframes talos-heatmap-fade-in{0%{opacity:0}to{opacity:1}}.talos-heatmap-loading-spinner-box{display:flex;align-items:center;gap:8px;padding:8px 16px;background:var(--talos-card-bg, #ffffff);border:1px solid var(--talos-heatmap-border);border-radius:8px;box-shadow:0 4px 12px #00000014;font-size:.85rem;font-weight:500;color:var(--talos-heatmap-text)}.talos-heatmap-loading-spinner-box .talos-heatmap-loading-spinner{width:16px;height:16px;color:var(--talos-primary-color, #4338ca);animation:talos-heatmap-spin .8s linear infinite}.talos-heatmap-legend{display:flex;align-items:center;gap:12px;margin-top:18px;padding-left:var(--talos-heatmap-row-header-width)}.talos-heatmap-legend-bound{font-size:.82rem;font-weight:600;color:var(--talos-heatmap-muted);min-width:12px}.talos-heatmap-legend-bar{height:8px;width:130px;border-radius:9999px;box-shadow:inset 0 1px 2px #00000014}\n"] }]
785
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], metrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "metrics", required: false }] }], selectedMetricId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMetricId", required: false }] }, { type: i0.Output, args: ["selectedMetricIdChange"] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }, { type: i0.Output, args: ["intervalChange"] }], dateRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateRange", required: false }] }, { type: i0.Output, args: ["dateRangeChange"] }], swapAxes: [{ type: i0.Input, args: [{ isSignal: true, alias: "swapAxes", required: false }] }, { type: i0.Output, args: ["swapAxesChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], hoursRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoursRange", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], days: [{ type: i0.Input, args: [{ isSignal: true, alias: "days", required: false }] }], colorScheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "colorScheme", required: false }] }], customColorStops: [{ type: i0.Input, args: [{ isSignal: true, alias: "customColorStops", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], cellShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellShape", required: false }] }], cellSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellSize", required: false }] }], fitWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitWidth", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], showRefresh: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefresh", required: false }] }], showExport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExport", required: false }] }], showExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExpand", required: false }] }], showSwapAxes: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSwapAxes", required: false }] }], showIntervalToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIntervalToggle", required: false }] }], showDateRangePicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDateRangePicker", required: false }] }], dateRangePresets: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateRangePresets", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], cellHover: [{ type: i0.Output, args: ["cellHover"] }], timeRangeChange: [{ type: i0.Output, args: ["timeRangeChange"] }], refresh: [{ type: i0.Output, args: ["refresh"] }], metricChange: [{ type: i0.Output, args: ["metricChange"] }], export: [{ type: i0.Output, args: ["export"] }] } });
786
+
787
+ class TalosHeatmapModule {
788
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
789
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapModule, imports: [TalosHeatmapComponent], exports: [TalosHeatmapComponent] });
790
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapModule, imports: [TalosHeatmapComponent] });
791
+ }
792
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosHeatmapModule, decorators: [{
793
+ type: NgModule,
794
+ args: [{
795
+ imports: [TalosHeatmapComponent],
796
+ exports: [TalosHeatmapComponent]
797
+ }]
798
+ }] });
799
+
800
+ /**
801
+ * Generated bundle index. Do not edit.
802
+ */
803
+
804
+ export { TalosHeatmapComponent, TalosHeatmapModule };
805
+ //# sourceMappingURL=weeehaoooz-talos-ui-data-viz-heatmap.mjs.map